NAV
c

Introduction

Document describes communication protocol between PC and AIRTLS devices. Protocol is used to transfer data over USB and Bluetooth Low Energy.

Hardware ID

typedef enum Descriptor_BoardType_e
{
    /* --- Misc --- */

    /** Horn */
    Descriptor_BoardType_AIRTLS_HA01 = 0x03,
    /** Board only (aka AM2) */
    Descriptor_BoardType_AIRTLS_MA02 = 0x02,
    /** LINO 230VAC (aka NeYo) */
    Descriptor_BoardType_AIRTLS_LA01 = 0x01,

    /* --- Anchors --- */

    /** Field anchor, mobile, LED */
    Descriptor_BoardType_AIRTLS_FA01 = 0x04,
    /** Field anchor nRF5340, mobile, LED */
    Descriptor_BoardType_AIRTLS_FA02 = 0x07,
    /** Anchor IP67 NaNoPi support */
    Descriptor_BoardType_AIRTLS_WA01 = 0x00,
    /** Anchor nRF5340 NaNoPi support */
    Descriptor_BoardType_AIRTLS_WA02 = 0x06,

    /* --- Tags --- */

    /** Tag Ball */
    Descriptor_BoardType_AIRTLS_TB01 = 0x3F,
    /** Tag PS65 with display */
    Descriptor_BoardType_AIRTLS_TA01 = 0x3E,

} Descriptor_BoardType_t;

typedef enum Descriptor_MCU_e
{
    Descriptor_MCU_nRF52 = 0, /**< nRF52 */
    Descriptor_MCU_nRF53 = 1, /**< nRF53 */

} Descriptor_MCU_t;

Hardware ID consists of Board Type and MCU Type. Parameter is used in protocol (field hwid) and formatted using following bit assignment with a single byte storage:

Bit Field
0-5 boardType
6-7 mcuType

Board Type defines type of the board and its place in the system. It is based on hardware pin configuration and takes following values:

Value Board type Description
0x03 HA01 Horn
0x02 MA02 Board only (aka AM2)
0x01 LA01 LINO 230VAC (aka NeYo)
0x04 FA01 Field anchor, mobile, LED
0x07 FA02 Field anchor nRF5340, mobile, LED
0x00 WA01 Anchor IP67 NaNoPi support
0x06 WA02 Anchor nRF5340 NaNoPi support
0x3F TB01 Tag Ball
0x3E TA01 Tag PS65 with display

MCU Type depends on the processor used by the device and could have following values:

Value MCU type
0 nRF52
1 nRF53

TLV

Type-Length-Value is format of encoding well known data.

General frame structure

struct Protocol_Frame_t
{
    uint8_t type;
    uint16_t length;
    uint8_t value[];
};

Example

Example structures and raw binary data

typedef enum FrameType_e
{
    FrameType_A = 0x00,
    FrameType_B = 0x01,
};

struct A_t
{
    uint8_t a1;
    uint16_t a2;
};

struct B_t
{
    uint16_t b1;
    char b2[];
};

uint8_t rawDataStream = {
    0x00, 0x03, 0x00, 0x00, 0x01,
    0x02, 0x01, 0x08, 0x00, 0x07,
    0x00, 0x41, 0x49, 0x52, 0x54,
    0x4c, 0x53
};

Let's consider some example:

There are two types of frames A and B. Frame type A is represented by type value 0x00, frame type B is represented by type value 0x01.

To start unpacking data we need to parse first three bytes of raw data stram. First byte 0x00 represents type of parsed message, so

Type = 0x00 - FrameType_A means that data in value field contains structure A_t. Structure A_t is well known, and has constant size, which is 3B. To confirm that we can read length field.

Second and third byte 0x03, 0x00 represents value length. It must be casted to uint16 value, so

Next 3 bytes 0x00, 0x01, 0x02 can be interpreted as A_t structure, so

But there is more data! We need to repeat the whole process. Take next byte 0x01, and interpret it as message type.

Type is equal to FrameType_B, so value field contains structure B_t, which size varies. To get actual B_t size we need to read length field, so we need to process next two bytes 0x08, 0x00,.

We know that b1 field is two bytes long, so to get length of b2 field we need to subtract 2B from read value length.

8 - 2 = 6

We now that in case of this message b2 field will be 6B long. Now we have all information to decode value field.

Dictionary

Supported frame types

Type Direction Description
0x01 Master Anchor ⟶ PC Time of Flight (ToF) data
0x02 Master Anchor ⟶ PC Serial data
0x03 Master Anchor ⟶ PC Admin distribution data
0x04 Master Anchor ⟶ PC Compressed Sensor data - XORDS
0x05 Master Anchor ⟶ PC Accelerometer data - bit-stitched
0x06 Master Anchor ⟶ PC Gyroscope data - bit-stitched
0x07 Master Anchor ⟶ PC Magnetometer data - bit-stitched
0x08 Master Anchor ⟶ PC Impact data
0x8B (139) PC ⟶ Master Anchor [⟶ UWB] Command set UWB config
0x8C (140) PC ⟶ Master Anchor [⟶ UWB] Command shutdown (kill)
0x8D (141) PC ⟶ Master Anchor [⟶ UWB] Command set board config
0x8E (142) PC ⟶ Master Anchor [⟶ UWB] Command set network config
0x8F (143) PC ⟶ Master Anchor [⟶ UWB] Command set random period
0x90 (144) PC ⟶ Master Anchor [⟶ UWB] Command set network start delay
0xC6 (198) PC ⟶ Master Anchor [⟶ UWB] Command factory reset
0xC8 (200) PC ⟶ Master Anchor [⟶ UWB] Command blink immediately
0xC9 (201) PC ⟶ Master Anchor [⟶ UWB] Command blink

0x01 - Time of Flight (ToF) data

C Structure format

typedef struct ToF_TagImpactReport_s
{
    uint8_t did[3];
    uint8_t hitCycleOffset;
    uint8_t motionByte;

} ToF_TagImpactReport_t;

typedef struct ToF_Tag_s
{
    uint8_t did[3];
    struct
    {
        uint8_t receivedByTag : 4;    /** bits 0:3 */
        uint8_t receivedByAnchor : 4; /** bits 4:7 */
    } rssi;

    uint16_t tof[];
} ToF_Tag_t;

typedef struct ToF_TagList_s
{
    struct
    {
        uint8_t numberOfToFs : 6; /** bits 0:5 */
        uint8_t precision : 2;    /** bits 6:7 */
    };

    uint8_t tagCount;
    uint8_t tagData[];

} ToF_TagList_t;

typedef struct Protocol_ToFReport_s
{
    uint8_t did[3];
    uint16_t cycleId;

    struct
    {
        uint8_t did[3];
        struct
        {
            uint8_t receivedByResponderAnchor : 4;   /** bits 0:3 */
            uint8_t receivedByTransmitterAnchor : 4; /** bits 4:7 */
        } rssi;

        uint16_t tof[4];
    } a2a;

    struct
    {
        uint8_t hitCycleOffset;
        uint8_t motionByte;
        uint8_t tagImpactReportCount;
    } imu;

    uint8_t tagListsCount;
    uint8_t tagListsData[];

} Protocol_ToFReport_t;

Frame example:

- One list of tags
- Two tags in list
- Each tag has 3 ToF reports, and ToF precision without shift (lsb = 0.5 cm)
- Two extra Tag impact reports
uint8_t rawData[] =
{
    /* TLV header: type = 1, length = 53 */
    0x01, 0x32, 0x00, 

    /* TLV value buffer (Protocol_ToFReport_t) */
    0x05, 0x0a, 0x0f, 0x88, 0x13, 

    /* a2a:
        did = [20, 40, 60],
        rssi.receivedByResponderAnchor = 5,
        rssi.receivedByTransmitterAnchor = 12,
        tof[0] = 300,
        tof[1] = 302,
        tof[2] = 301,
        tof[3] = 303
    */
    0x14, 0x28, 0x3c, 0x5c, 0x2c, 0x01, 0x2e, 0x01, 0x2d, 0x01, 0x2f, 0x01, 

    /* imu:
        hitCycleOffset = 40;
        motionByte = 0x80 | 10; - Anchor faced up | motion '10'
        tagImpactReportCount = 2;
    */
    0x28, 0x8a, 0x02, 

    /* tagListsCount = 1 */
    0x01,

    /* Tag lists data (ToF_TagList_t [])*/

    /* List 0 data:
        precision    = 0,
        numberOfToFs = 3,
        tagCount     = 2,
    */
    0x03, 0x02,

    /* Tag data (ToF_Tag_t []) */

    /* Tag 0 data:
        did = [33, 34, 35],
        rssi.receivedByAnchor = 10,
        rssi.receivedByTag = 12,
        tof[0] = 200,
        tof[1] = 201,
        tof[2] = 202
    */
    0x21, 0x22, 0x23, 0xac, 0xc8, 0x00, 0xc9, 0x00,
    0xca, 0x00,

    /* Tag 1 data:
        did = [33, 34, 36],
        rssi.receivedByAnchor = 11,
        rssi.receivedByTag = 13,
        tof[0] = 204,
        tof[1] = 205,
        tof[2] = 206
    */
    0x21, 0x22, 0x24, 0xbd, 0xcc, 0x00, 0xcd, 0x00,
    0xce, 0x00,

    /* Impact report 1:
        did = [33, 34, 35],
        hitCycleOffset = 17;
        motionByte     = 27;
    */
    0x21, 0x22, 0x23, 0x11, 0x1b, 

    /* Impact report 2:
        did = [33, 34, 36],
        hitCycleOffset = 22;
        motionByte     = 50;
    */
    0x21, 0x22, 0x24, 0x16, 0x32, 
}

Frame transmitted from the device (Master Anchor) to the PC after reception of ToF report from other Anchor (in OFFLOAD slot), and after OFFLOAD, when we want to transmit ToF report from MasterAnchor.

Frame format changes dynamically depending on type of tags (number of ToFs), and tag count. Frame consists of three well defined nested structures (3 levels):

Structure nesting example

ToF Report contains two tag lists (two tag types). First list contains three tags of given type, second list contains single tag of other type (not related to example in code).

RSSI encoding

RSSI value in described packet is stored as 4-bit packed value (range 0-15) specifying value from -78dB (packed as 0) to -93dB (packed as 15) with 1dB resolution.

Protocol_ToFReport_t fields

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Anchor (or Master Anchor) ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5-7 3 bytes (array uint8) a2a.did Three bytes long Target Anchor ID (Target Anchor that performed ranging)
8 [bits 0-3] 4 bits (uint8) a2a.rssi.receivedByResponderAnchor 4bit packed RSS value of frame received by responder Anchor
8 [bits 4-7] 4 bits (uint8) a2a.rssi.receivedByTransmitterAnchor 4bit packed RSS value of frame received by transmitter Anchor (initiator)
9-10 2 bytes (uint16) a2a.tof[0] ToF value #0
11-12 2 bytes (uint16) a2a.tof[1] ToF value #1
13-14 2 bytes (uint16) a2a.tof[2] ToF value #2
15-16 2 bytes (uint16) a2a.tof[3] ToF value #3
17 1 byte (uint8) imu.hitCycleOffset Impact hit detection in miliseconds relative to the start of the cycle
18 1 byte (uint8) imu.motionByte Anchor motion byte characterizing device movement
19 1 byte (uint8) imu.tagImpactReportCount Number of Tag impact reports at the end of the ToF report frame
20 1 byte (uint8) tagListsCount Defines number of ToF_TagList_t structures in tagListsData buffer (number of different tag configurations)
21+ n bytes (array uint8) tagListsData Contains list of ToF_TagList_t structures

ToF_TagList_t fields

Byte Storage Field Description
0 [bits 0-5] 6 bits (uint8) numberOfToFs 6bit value that defines number of ToF values (uint16) in each ToF_Tag_t structure
0 [bits 6-7] 2 bits (uint8) precision 2bit value that defines ToF value shift. (0 = unchanged (lsb = 0.5cm), 1 = divided by 2 (lsb = 1cm), 2 = divided by 4 (lsb = 2cm), 3 = divided by 8 (lsb = 4cm)).
1 1 bytes (uint8) tagCount Defines how many ToF_Tag_t structures are in tagData buffer
2+ n bytes (array uint8) tagData Contains array of ToF_Tag_t structures

ToF_Tag_t fields

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3 [bits 0-3] 4 bits (uint8) rssi.receivedByTag 4bit packed RSS value of frame received by Tag
3 [bits 4-7] 4 bits (uint8) rssi.receivedByAnchor 4bit packed RSS value of frame received by Anchor
4+ n * 2 bytes (array uint16) tof Array ToF values (uint16). Array length is defined in parent ToF_TagList_t structure

ToF_TagImpactReport_t fields

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3 1 byte (uint8) hitCycleOffset Impact hit detection in miliseconds relative to the start of the cycle
4 1 byte (uint8) motionByte Motion byte characterizing device movement

0x02 - Serial data

C Structure format

typedef struct Protocol_Sensors_s
{
    uint8_t did[3];
    uint16_t cycleId;
    uint8_t slotId;
    uint8_t data[];
} Protocol_Sensors_t;

Frame example c uint8_t rawData[] = { /* TLV header: type = 2, length = 12 */ 0x02, 0x0c, 0x00, /* Value buffer did = [10, 20, 30], cycleId = 10000, slotId = 50 data = 'AIRTLS' */ 0x0a, 0x14, 0x1e, 0x10, 0x27, 0x32, 0x41, 0x49, 0x52, 0x54, 0x4c, 0x53, }

Frame transmitted from the device (Master Anchor) to the PC after reception of TRESPONSE frame form device. Frame contains serial data form the device. Frame length depends on serial data length.

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5 1 byte (uint8) slotId ID of the slot (seat) in which data was sent
6+ n bytes (array uint8) data Raw serial data transmitted from the device. Field has variable size

0x03 - Admin Distribution Info

C Structure format

typedef struct Protocol_AdminDistributionInfo_s
{
    uint8_t did[3];
    uint16_t cycleId;

    /* Constants */

    uint8_t fwVersionMajor;
    uint8_t fwVersionMinor;
    uint8_t hwid;
    uint8_t mac[6];

    /* Config */
    struct
    {
        uint8_t deviceOffset;
        uint8_t frequency;
        uint8_t seat;
    } cycle;

    uint8_t serialNumber[4];
    char name[9];
    char group[3];
    uint8_t license[2];

    struct 
    {
        uint8_t txPowerPreset;
    } bt;

    struct
    {
        int8_t ch3AntennaDelay;
        int8_t ch5AntennaDelay;
        uint8_t txPowerPreset;
    } uwb;

    struct
    {
        uint8_t boardConfig;
        uint8_t pressureCalibration;

        struct
        {
            uint8_t x;
            uint8_t y;
            uint8_t z;
        } magnetoBias;

        struct
        {
            uint8_t x;
            uint8_t y;
            uint8_t z;
        } magnetoScalar;

        struct
        {
            uint8_t x;
            uint8_t y;
            uint8_t z;
        } accelerometerBias;

    } sensorsConfig;

    /* Dynamic sensor data */
    struct
    {
        uint8_t vbat;
        uint8_t motionByte;
        uint8_t hit;
        uint8_t pressure;
        uint8_t heartRate;
        uint8_t mox;
    } sensorsData;

    /* Indicates which data is valid in the above set */
    uint8_t valid[7];

    uint8_t slowTagsDetected;
    Protocol_AdminDistributionInfo_SlowTag_t slowTags[];

} Protocol_AdminDistributionInfo_t;

typedef struct Protocol_AdminDistributionInfo_SlowTag_s
{
     /** Short device ID */
    uint8_t did[3];

    uint8_t seat;       /**< Device seat */
    uint8_t vbat;       /**< Packed battery voltage */
    uint8_t hwid;       /**< Board type HWID */
    uint8_t motionByte; /**< Motion byte characterizing device movement */

} Protocol_AdminDistributionInfo_SlowTag_t;

Frame example

uint8_t rawData[] =
{
    /* TLV header: type = 3, length = 63 */
    0x03, 0x3f, 0x00, 

    /* Value buffer (Protocol_AdminDistributionInfo_t):
        did = [5, 10, 15],
        cycleId = 7000,
        fwVersionMajor = 1,
        fwVersionMinor = 2,
        hwid = 3,
        mac = [0x11, 0x12, 0x13, 0x14, 0x15, 0x16],

        cycle.deviceOffset = 0,
        cycle.frequency = 50,
        cycle.seat = 34,

        serialNumber = [1, 0 ,0 ,0],
        name = "AIRTLS",
        group = "AB",
        license = [221, 222],

        bt.txPowerPreset = 2,

        uwb.ch3AntennaDelay = 99,
        uwb.ch5AntennaDelay = 100,
        uwb.txPowerPreset = 1,

        sensorsConfig.boardConfig = 0x00,
        sensorsConfig.pressureCalibration = 10,
        sensorsConfig.magnetoBias.x = 7,
        sensorsConfig.magnetoBias.y = 8,
        sensorsConfig.magnetoBias.z = 9,
        sensorsConfig.magnetoScalar.x = 4,
        sensorsConfig.magnetoScalar.y = 5,
        sensorsConfig.magnetoScalar.z = 6,
        sensorsConfig.accelerometerBias.x = 1,
        sensorsConfig.accelerometerBias.y = 2,
        sensorsConfig.accelerometerBias.z = 3,

        sensorsData.vbat = 30,
        sensorsData.motionByte = 1,
        sensorsData.hit = 70,
        sensorsData.pressure = 98,
        sensorsData.heartRate = 99,
        sensorsData.mox = 100,

        valid = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],

        slowTagsDetected = 0,
    */
    0x05, 0x0a, 0x0f, 0x58, 0x1b, 0x01, 0x02, 0x03, 
    0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x00, 0x32, 
    0x22, 0x01, 0x00, 0x00, 0x00, 0x41, 0x49, 0x52, 
    0x54, 0x4c, 0x53, 0x00, 0x00, 0x00, 0x41, 0x42, 
    0x00, 0xdd, 0xde, 0x02, 0x63, 0x64, 0x01, 0x00, 
    0x0a, 0x07, 0x08, 0x09, 0x04, 0x05, 0x06, 0x01, 
    0x02, 0x03, 0x1e, 0x01, 0x46, 0x62, 0x63, 0x64, 
    0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00
};

Frame with administration data transmitted from the connected anchor to the PC periodically - at most one frame per cycle, used to synchronize device database with the host. The database contains basic information about anchor and tags seen in the network.
Most of the time anchor provides information about devices that have their administration data changed. Periodically it enters full DDM synchronization mode in which it dumps all available record in interleaved mode with nominal priority entries. This method allows to eventually reconstruct anchor database in host application regardless of the moment that the ACP connection was created.
Slow update rate devices (those not active in every cycle) are not part of the core data structure, but instead there are appended at the end in form of a variable size list with basic device properties.

Protocol_AdminDistributionInfo_t fields

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Device (Tag, or Anchor) ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5 1 byte (uint8) fwVersionMajor Firmware version major number
6 1 byte (uint8) fwVersionMinor Firmware version minor number
7 1 byte (uint8) hwid Hardware ID with board type (6 bits) and chip type (highest 2 bits)
8-13 6 bytes (array uint8) mac 48b MAC Address
14 1 byte (uint8) cycle.deviceOffset Cycle offset for low speed tags
15 1 byte (uint8) cycle.frequency Device frequency correlating to number of ToF values provided:
- 0 - unknown
- 1 - 25Hz
- 2 - 50Hz
- 3 - 75Hz
- 4 - 100Hz
- 5 - 125Hz
- 6 - 150Hz
16 1 byte (uint8) cycle.seat Primary seat assigned to device, that is the first seat used by the device in a cycle.
17-20 4 bytes (array uint8) serialNumber 4 Byte Serial number
21-29 9 bytes (array char) name Device name string
30-32 3 bytes (array char) group Device group name string
33-34 2 bytes (array uint8) license License buffer
35 1 byte (uint8) bt.txPowerPreset Bluetooth TX power preset. TODO: define presets
36 1 byte (uint8) uwb.ch3AntennaDelay UWB Antenna delay for UWB channel 1-3 - offset from default value.
37 1 byte (uint8) uwb.ch5AntennaDelay UWB Antenna delay for UWB channel 5 - offset from default value.
38 1 byte (uint8) uwb.txPowerPreset UWB TX power preset. TODO: define presets
39 1 byte (uint8) sensorsConfig.boardConfig Board config
40 1 byte (uint8) sensorsConfig.pressureCalibration Sensor calibration value which is substracted from the measured pressure value.
41 1 byte (uint8) sensorsConfig.magnetoBias.x Sensor calibration value TODO: units
42 1 byte (uint8) sensorsConfig.magnetoBias.y Sensor calibration value TODO: units
43 1 byte (uint8) sensorsConfig.magnetoBias.z Sensor calibration value TODO: units
44 1 byte (uint8) sensorsConfig.magnetoScalar.x Sensor calibration value TODO: units
45 1 byte (uint8) sensorsConfig.magnetoScalar.y Sensor calibration value TODO: units
46 1 byte (uint8) sensorsConfig.magnetoScalar.z Sensor calibration value TODO: units
47 1 byte (uint8) sensorsConfig.accelerometerBias.x Sensor calibration value TODO: units
48 1 byte (uint8) sensorsConfig.accelerometerBias.y Sensor calibration value TODO: units
49 1 byte (uint8) sensorsConfig.accelerometerBias.z Sensor calibration value TODO: units
50 1 byte (uint8) sensorsData.vbat Battery voltage value encoded using following format:
- minimum (binary 0) = 2754mV
- maximum (binary 255) = 4250mV
- resolution = ~5.84mV
51 1 byte (uint8) sensorsData.motionByte Motion byte characterizing device movement
52 1 byte (uint8) sensorsData.hit Impact hit detection in miliseconds relative to the start of the cycle. NOTE: It is "last known" impact value.
53 1 byte (uint8) sensorsData.pressure Pressure sensor value encoded using following format:
- minimum (binary 0) = athmospheric pressure
- maximum (binary 255) = 1.1 Bar above athmospheric pressure
- resolution = ~4.3mBar
Presented value already takes into account pressureCalibration value, so no additional caluculations are required.
54 1 byte (uint8) sensorsData.heartRate Heart Rate sensor value. TODO: units
55 1 byte (uint8) sensorsData.mox MOX sensor value. TODO: units
56-62 7 bytes (array uint8) valid Indicates which packet fields are valid. Each bit correlates to single single packet field starting from offset 5 (fwVersionMajor), i.e:
- valid[0]:bit0 -> field @ 5 -> fwVersionMajor
- valid[0]:bit1 -> field @ 6 -> fwVersionMinor
- valid[0]:bit7 -> field @ 12 -> mac[4]
- valid[1]:bit0 -> field @ 13 -> mac[5]
All fields without corresponding valid bit set should be treated as not available. Depending on the device type they may be updated at some later time when the anchor receives proper data over the internal system network.
63 1 byte (uint8) slowTagsDetected Number of detected slow update rate tags in cycle cycleId

Protocol_AdminDistributionInfo_SlowTag_t fields

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Device ID
3 1 byte (uint8) seat Primary seat assigned to device, that is the first seat used by the device in a cycle.
4 1 byte (uint8) vbat Battery voltage value encoded using following format:
- minimum (binary 0) = 2754mV
- maximum (binary 255) = 4250mV
- resolution = ~5.84mV
5 1 byte (uint8) hwid Hardware ID with board and chip types.
6 1 byte (uint8) motionByte Motion byte characterizing device movement

0x04 - Compressed sensor data

C Structure format

typedef struct Protocol_Sensors_s
{
    uint8_t did[3];
    uint16_t cycleId;
    uint8_t slotId;
    uint8_t data[];
} Protocol_Sensors_t;

Frame example

uint8_t rawData[] =
{
    /* TLV header: type = 4, length = 106 */
    0x04, 0x6a, 0x00, 
    /* Value buffer 
        did = [10, 20, 30],
        cycleId = 10000,
        slotId = 50
        data = <numbers form 0-99 - AKA dummy bytes>
    */
    0x0a, 0x14, 0x1e, 0x10, 0x27, 0x32, 0x00, 0x01, 
    0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 
    0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 
    0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 
    0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 
    0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 
    0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 
    0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 
    0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40, 0x41, 
    0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 
    0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 
    0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 
    0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60, 0x61, 
    0x62, 0x63, 
}

Frame transmitted from the device (Master Anchor) to the PC after reception of TRESPONSE frame form device. Frame contains compressed data form sensor. Compressed data format can be used to optimize communication interface capacity, and reduce CPU usage on anchor, because in this case anchor just copies data received from other devices - no extra processing needed.

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5 1 byte (uint8) slotId ID of the slot (seat) in which data was sent
6+ n bytes (array uint8) data Compressed (raw) data transmitted from the device. Field has variable size

0x05 - Accelerometer sensor data

C Structure format

typedef struct Protocol_Sensors_s
{
    uint8_t did[3];
    uint16_t cycleId;
    uint8_t slotId;
    uint8_t data[];
} Protocol_Sensors_t;

Frame example

uint8_t rawData[] =
{
    /* TLV header: type = 5, length = 114 */
    0x05, 0x72, 0x00, 

    /* Value buffer 
        did = [10, 20, 30],
        cycleId = 1234,
        slotId = 77
    */
    0x0a, 0x14, 0x1e, 0xd2, 0x04, 0x4d, 

    /* data = Bit-Stitched 18b accelerometer samples */
    0x1c, 0xf4, 
    0x67, 0x24, 0xe0, 0x57, 0x80, 0x04, 0xfd, 0x1f, 
    0x09, 0x4c, 0x16, 0x80, 0x41, 0x7f, 0x46, 0x02, 
    0x8c, 0x05, 0x18, 0xd0, 0xbf, 0x8e, 0xc0, 0x6e, 
    0x01, 0x0d, 0xf4, 0x5b, 0x23, 0xe0, 0x5a, 0xc0, 
    0xfc, 0xfc, 0xde, 0x08, 0xfc, 0x16, 0x00, 0xb0, 
    0x22, 0x02, 0x80, 0xa3, 0xff, 0xf9, 0xff, 0xd7, 
    0xff, 0x1f, 0x4e, 0x79, 0xc9, 0x90, 0xfb, 0x03, 
    0xe8, 0x9d, 0x0f, 0x07, 0xfd, 0x19, 0x09, 0xf8, 
    0x15, 0x20, 0x41, 0xff, 0x47, 0x02, 0x93, 0x05, 
    0x60, 0xd0, 0x9f, 0x91, 0x00, 0x63, 0x01, 0x06, 
    0xf4, 0xaf, 0x23, 0xb0, 0x5b, 0x40, 0x03, 0xfd, 
    0xd6, 0x08, 0xb8, 0x16, 0x30, 0x3f, 0xbf, 0x37, 
    0x02, 0xbf, 0x05, 0x34, 0xd0, 0x6f, 0x8d, 0x80, 
    0x6b, 0x01, 
}

/* Samples used in example above */
static const int32_t samples[] = {
    -3044,      2329,        1406,
    -3054,      2335,        1427,
    -3048,      2329,        1420,
    -3066,      2283,        1467,
    -3059,      2262,        1454,
    -3085,      2270,        1471,
    -120064,    -131064,     130979,
    131070,     131069,      124216,
    -28471,     -130818,     63966,
    -3044,      2329,        1406,
    -3054,      2335,        1427,
    -3048,      2329,        1420,
    -3066,      2283,        1467,
    -3059,      2262,        1454,
    -3085,      2270,        1471,
    -3059,      2262,        1454,
};

Frame transmitted from the device (Master Anchor) to the PC after reception of TRESPONSE frame form device.

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5 1 byte (uint8) slotId ID of the slot (seat) in which data was sent
6+ n bytes (array uint8) data Bit-stitched accelerometer samples

Data array contains bit-stitched set of accelerometer samples. Each sample is 18 bit signed int.

Bit-stitching was implemented to increase the capacity of communication interface. It reduces number of unused bits to 0.

(Well, there will be some spare bits to fill up last byte...)

Accelerometer data format:

IMU Bit Stiching

16 Samples
7 Samples

0x06 - Gyroscope sensor data

C Structure format

typedef struct Protocol_Sensors_s
{
    uint8_t did[3];
    uint16_t cycleId;
    uint8_t slotId;
    uint8_t data[];
} Protocol_Sensors_t;

Frame example

uint8_t rawData[] =
{
    /* TLV header: type = 6, length = 120 */
    0x06, 0x78, 0x00, 
    /* Value buffer 
        did = [10, 20, 30],
        cycleId = 4321,
        slotId = 77
    */
    0x0a, 0x14, 0x1e, 0xe1, 0x10, 0x4d, 
    /* Bit-stitched 19b gyroscope samples with 8b header */
    0x79, 0xfd, 
    0xdf, 0xf8, 0xff, 0x6a, 0x00, 0x66, 0xfd, 0xbf, 
    0xf1, 0x7f, 0x89, 0x00, 0x28, 0xfa, 0x7f, 0xe3, 
    0xff, 0xab, 0x01, 0x90, 0xf9, 0x7f, 0xd6, 0xff, 
    0x45, 0x02, 0xa0, 0xe7, 0x7f, 0xa2, 0xff, 0x8b, 
    0x04, 0x60, 0xe3, 0xff, 0x05, 0xff, 0xef, 0x0b, 
    0x80, 0xa7, 0xff, 0x37, 0xfe, 0xdf, 0x17, 0x00, 
    0x64, 0xff, 0x6f, 0xfc, 0x5f, 0x22, 0x00, 0x59, 
    0xff, 0x97, 0xf9, 0xbf, 0x48, 0x00, 0x0a, 0xfe, 
    0xbf, 0xf1, 0xff, 0xbe, 0x00, 0x6c, 0xfc, 0x7f, 
    0xd6, 0xff, 0x12, 0x01, 0xd8, 0xf8, 0xbf, 0xa2, 
    0xff, 0x57, 0x03, 0x40, 0xf4, 0x7f, 0x3d, 0xff, 
    0x8b, 0x04, 0x60, 0xe3, 0xff, 0x9e, 0xfe, 0xef, 
    0x0b, 0xc0, 0xc6, 0xff, 0xf3, 0xfa, 0xbf, 0x1a, 
    0x80, 0x8d, 0xff, 0x23, 0xfb, 0x5f, 0x22, 0x00, 
}

/* Samples used in example above */
static const int32_t samples[] = {
    -647, -229, 427,
    -333, -229, 274,
    -374, -229, 427,
    -206, -167, 290,
    -390, -188, 290,
    -229, -251, 381,
    -354, -229, 381,
    -312, -229, 274,
    -167, -206, 290,
    -251, -229, 381,
    -229, -333, 274,
    -229, -374, 427,
    -188, -390, 290,
    -229, -354, 381,
    -229, -647, 427,
    -229, -312, 274
};

Frame transmitted from the device (Master Anchor) to the PC after reception of TRESPONSE frame form device.

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5 1 byte (uint8) slotId ID of the slot (seat) in which data was sent
6+ n bytes (array uint8) data Bit-stitched 19b gyroscope samples

Gyroscope data format:

IMU Bit Stiching

16 Samples
7 Samples

0x07 - Magnetometer sensor data

C Structure format

typedef struct Protocol_Sensors_s
{
    uint8_t did[3];
    uint16_t cycleId;
    uint8_t slotId;
    uint8_t data[];
} Protocol_Sensors_t;

Frame example

uint8_t rawData[] =
{
    /* TLV header: type = 7, length = 72 */
    0x07, 0x48, 0x00, 
    /* Value buffer 
        did = [10, 20, 30],
        cycleId = 1111,
        slotId = 33
    */
    0x0a, 0x14, 0x1e, 0x57, 0x04, 0x21, 
    /* Bit-stitched 11b magnetometer samples with 8b header */
    0x08, 0xef, 
    0xed, 0x95, 0xfb, 0xcd, 0x5b, 0x29, 0xfb, 0xfb, 
    0xb7, 0x53, 0xf6, 0xf7, 0x6f, 0xa1, 0xfc, 0xef, 
    0xde, 0x42, 0x19, 0xe1, 0xbe, 0x9d, 0x72, 0xbf, 
    0x79, 0x7b, 0xe5, 0x7f, 0xfb, 0x16, 0xca, 0xfd, 
    0xfe, 0xad, 0x94, 0xfd, 0xcd, 0xdb, 0x2b, 0xff, 
    0xfb, 0xb7, 0x50, 0x46, 0x78, 0x6f, 0xa7, 0xdc, 
    0x6f, 0xdf, 0x4a, 0xd9, 0xdf, 0xbf, 0xbd, 0x32, 
    0xc2, 0x79, 0x0b, 0x65, 0x7f, 0xfb, 0x76, 0xca,
}

/* Samples used in example above */
static const int32_t samples[] = {
    -248, -579, -425,
    -259, -580, -430,
    -258, -577, -429,
    -258, -577, -432,
    -257, -579, -432,
    -248, -578, -429,
    -259, -580, -425,
    -257, -578, -432,
    -259, -577, -430,
    -258, -580, -425,
    -257, -577, -432,
    -248, -579, -429,
    -259, -578, -430,
    -258, -577, -425,
    -248, -580, -432,
    -258, -578, -429
};

Frame transmitted from the device (Master Anchor) to the PC after reception of TRESPONSE frame form device.

Byte Storage Field Description
0-2 3 bytes (array uint8) did Three bytes long Tag ID
3-4 2 bytes (uint16) cycleId ID of the cycle in which the data was sent
5 1 byte (uint8) slotId ID of the slot (seat) in which data was sent
6+ n bytes (array uint8) data Bit-stitched 11b magnetometer samples

Magnetometer data format:

IMU Bit Stiching

16 Samples
7 Samples

0x8B - Command Set UWB Config

C Structure format

typedef struct SM_Protocol_CommandSetUWBConfig_s
{
    struct 
    {
        uint8_t did[3];
        int8_t ch3;
        int8_t ch5;
        uint8_t txPower;
    } device[2];

} SM_Protocol_CommandSetUWBConfig_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 139, length = 12 */
0x8b, 0x0c, 0x00, 
/* Value buffer */

/* Device 0:
did 0 = [1, 2, 3],
ch3 = -5
ch5 = 5
txPower = 1
*/
0x01, 0x02, 0x03, 0xfb, 0x05, 0x01, 

/* Device 1:
did 0 = [16, 32, 48],
seat = 1 
ch3 = 10
ch5 = -10
txPower = 1
*/
0x10, 0x20, 0x30, 0x0a, 0xf6, 0x01, 
}

Frame transmitted from the PC to the device (Master Anchor) to change UWB configuration. UWB settings will be synced (saved in non-volatile memory) 500ms after processing of the command.

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3 1 byte (int8) ch3 0 Antenna delay offset from default value (16456) for UWB channels 1-3
4 1 byte (int8) ch5 0 Antenna delay offset from default value (16456) for UWB channel 5
5 1 byte (uint8) txPower 0 UWB TX power profile encoded using following format:
- minimum: 0 = 0 dB
- maximum: 61 = 30.5 dB
- resolution = 0.5 dB
Values over 61 are not allowed.
6-8 3 bytes (array uint8) did 1 Three bytes long Node ID
9 1 byte (int8) ch3 1 Antenna delay offset from default value (16456) for UWB channels 1-3
10 1 byte (int8) ch5 1 Antenna delay offset from default value (16456) for UWB channel 5
11 1 byte (uint8) txPower 1 UWB TX power profile encoded using following format:
- minimum: 0 = 0 dB
- maximum: 61 = 30.5 dB
- resolution = 0.5 dB
Values over 61 are not allowed.

0x8C - Command Shutdown (kill)

C Structure format

typedef struct  SM_Protocol_CommandShutdown_s
{
    struct
    {
        uint8_t did[3];
    } device[4];

} SM_Protocol_CommandShutdown_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 140, length = 12 */
0x8c, 0x0c, 0x00, 
/* Value buffer 
    did 0 = [1, 2, 3],
    did 1 = [0, 0, 0], (unused)
    did 2 = [33, 34, 35],
    did 3 = [18, 34, 50],
*/
0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x21, 0x22, 
0x23, 0x12, 0x22, 0x32, 
}

Frame transmitted from the PC to the device (Master Anchor). The request is used to power-off one or many network devices. The target node must be seen by the Master Anchor connected to the software system. Unused devices fields should be set to invalid ID: [0x00, 0x00, 0x00].

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3-5 3 bytes (array uint8) did 1 Three bytes long Node ID
6-8 3 bytes (array uint8) did 2 Three bytes long Node ID
9-11 3 bytes (array uint8) did 3 Three bytes long Node ID

0x8D - Command Set Board Config

C Structure format

typedef struct  SM_Protocol_CommandSetBoardConfig_s
{
    struct
    {
        uint8_t did[3];
        uint8_t boardConfig;

    } device[3];

} SM_Protocol_CommandSetBoardConfig_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 141, length = 12 */
0x8d, 0x0c, 0x00, 
/* Value buffer 
    did 0 = [1, 2, 3], board config: 0x01
    did 1 = [33, 34, 35], board config: 0xAA
    did 2 = [0, 0, 0] (unused)
*/
0x01, 0x02, 0x03, 0x01,
0x21, 0x22, 0x23, 0xAA,
0x00, 0x00, 0x00, 0x00,
}

Frame transmitted from the PC to the device (Master Anchor). The request is used to change board configuration parameters of one or many network devices. The target node must be seen by the Master Anchor connected to the software system. Unused devices fields should be set to invalid ID: [0x00, 0x00, 0x00].

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3 1 byte (bitmask) board config 0 Board configuration
4-6 3 bytes (array uint8) did 1 Three bytes long Node ID
7 1 byte (bitmask) board config 1 Board configuration
8-10 3 bytes (array uint8) did 2 Three bytes long Node ID
11 1 byte (bitmask) board config 2 Board configuration

Board configuration encoding:

Bit Field Description
0 imu on/off Controls whether the tag outputs IMU measurement data stream, 0: off, 1: on. When disabled no samples are reported with ACP types 4-8 from the node. Movement indicators like motion byte and hit detection remain functional regardless of the configuration.
1 sleep on/off Controls whether the device can enter sleep mode, comletely suspending its operation in UWB network, 0: off, 1: on. Sleep entry can be caused by:
- a tag remaining idle (not moving) for some time
- a tag not detecting UWB network presence
- a field anchor detecting itself as no longer in upright position
2 sleep shallow on/off Controls whether the tag can enter shallow sleep mode, temporarily suspending its operation in UWB network when remaining idle for short time, 0: off, 1: on. The tag will provide data on existing seat but with noticeable breaks used to improve device battery lifetime.

0x8E - Command Set Network Configuration

C Structure format

typedef struct SM_Protocol_CommandSetNetworkDeviceConfig_s
{
    struct
    {
        uint8_t did[3];
        uint8_t seat;
        uint8_t frequency;

        struct
        {
            uint8_t allocatorType : 2; /** bits 0:1 Allocator type:
                                                - 0 Fixed,
                                                - 1 Auto Strict,
                                                - 2 Auto Relaxed */
            uint8_t deviceType : 3;    /** bits 2:4 Device type: 
                                                - 0 Default
                                                - 1 Reserved
                                                - 2 Anchor
                                                - 3 Tag
                                                - 4-7 Reserved */
            uint8_t reserved : 3;      /** bits 5:7 For future use */
        } config;

    } device[2];

} SM_Protocol_CommandSetNetworkDeviceConfig_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 142, length = 12 */
0x8e, 0x0c, 0x00, 
/* Value buffer */

/* Device 0:
did 0 = [1, 2, 3],
seat = 18,
frequency = 50Hz (5),
allocator type = Auto Strict,
device type = Default
*/
0x01, 0x02, 0x03, 0x12, 0x05, 0x01, 

/* Device 1:
did 1 = [16, 32, 48],
seat = 5,
frequency = 50Hz (5),
allocator type = Auto Strict,
device type = Default
*/
0x10, 0x20, 0x30, 0x05, 0x05, 0x01,
};

Frame transmitted from the PC to the device (Master Anchor) to change device network configuration which defines its operational parameters for UWB network visibility. Processing of the command requires receiving nodes to perform system reset in order to apply new configuration.

General rules:

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3 1 byte (uint8) seat 0 Device seat
4 1 byte (uint8) frequency 0 Device nominal frequency:
- 0 - reserved
- 1 - random
- 2 - very slow
- 3 - slow
- 4 - 25Hz
- 5 - 50Hz
- 6 - 75Hz
- 7 - 100Hz
- 8 - 125Hz
- 9 - 150Hz
5 [bits 0-1] 2 bits enum allocator type 0 Seat allocator type used on the device:
- 0 - Fixed/Manual
- 1 - Automatic Strict
- 2 - Automatic Relaxed
5 [bits 2-4] 3 bits enum device type 0 Device type configuration
- 0 - default
- 1 - reserved
- 2 - anchor
- 3 - tag
6-8 3 bytes (array uint8) did 1 Three bytes long Node ID
9 1 byte (uint8) seat 1 Device seat
10 1 byte (uint8) frequency 1 Device nominal frequency
11 [bits 0-1] 2 bits enum allocator type 1 Seat allocator type used on the device
11 [bits 2-4] 3 bits enum device type 1 Device type configuration

0x8F - Command Set Random Period

C Structure format

typedef struct SM_Protocol_CommandSetRandomPeriod_s
{
    struct
    {
        uint8_t did[3];
        uint16_t period;

    } device[2];

    uint8_t padding[2];

} SM_Protocol_CommandSetRandomPeriod_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 143, length = 12 */
0x8f, 0x0c, 0x00, 
/* Value buffer */

/* Device 0:
did 0 = [1, 2, 3],
period = 1000 seconds
*/
0x01, 0x02, 0x03, 0xE8, 0x03,

/* Device 1:
did 1 = [16, 32, 48],
period = 32 seconds
*/
0x10, 0x20, 0x30, 0x20, 0x00,

/* Padding */
0x00, 0x00,
};

Frame transmitted from the PC to the device (Master Anchor) to change configuration of target nodes random period option, used to define update rate period when tag is operating with random frequency. Settings will be synced (saved in non-volatile memory) 500ms after processing of the command.

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3-4 2 bytes (uint16) period 0 Random period in seconds
5-7 3 bytes (array uint8) did 1 Three bytes long Node ID
8-9 2 bytes (uint16) period 1 Random period in seconds
10-11 2 bytes padding Padding bytes with arbitrary values

0x90 - Command Set Network Start Delay

C Structure format

typedef struct SM_Protocol_CommandSetNetworkStartDelay_s
{
    struct
    {
        uint8_t did[3];
        uint8_t delayInSec;

    } device[3];

} SM_Protocol_CommandSetNetworkStartDelay_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 144, length = 12 */
0x90, 0x0c, 0x00, 
/* Value buffer */

/* Device 0:
did 0 = [1, 2, 3],
delay = 5 seconds
*/
0x01, 0x02, 0x03, 0x05,

/* Device 1:
did 1 = [16, 32, 48],
delay = 0 seconds
*/
0x10, 0x20, 0x30, 0x00,

/* Device 2:
did 2 = [0, 0, 0],
delay = 0 seconds
*/
0x00, 0x00, 0x00, 0x00,
};

Frame transmitted from the PC to the device (Master Anchor) to change configuration of target nodes network start delay settings option, used to define maximum time an anchor is scanning for network presence before deciding to create a new one. Settings will be synced (saved in non-volatile memory) 500ms after processing of the command.

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3 byte (uint8) delay 0 Network start delay in seconds
4-6 3 bytes (array uint8) did 1 TNetwork start delay in seconds
7 byte (uint8) delay 1 Random period in seconds
8-10 3 bytes (array uint8) did 2 Network start delay in seconds
11 byte (uint8) delay 2 Random period in seconds

0xC6 - Command Factory Reset

C Structure format

typedef struct SM_Protocol_CommandFactoryReset_s
{
    struct
    {
        SM_Protocol_DID_t did;
    } device[4];

} SM_Protocol_CommandFactoryReset_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 198, length = 12 */
0xc6, 0x0c, 0x00, 
/* Value buffer 
    did 0 = [1, 2, 3],
    did 1 = [0, 0, 0], (unused)
    did 2 = [33, 34, 35],
    did 3 = [18, 34, 50],
*/
0x01, 0x02, 0x03, 0x00, 0x00, 0x00, 0x21, 0x22, 
0x23, 0x12, 0x22, 0x32, 
}

Frame transmitted from the PC to the device (Master Anchor). The request is used to erase all settings of one or many network devices. The target node must be seen by the Master Anchor connected to the software system. Target device will reboot during the reset. Unused devices fields should be set to invalid ID: [0x00, 0x00, 0x00].

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3-5 3 bytes (array uint8) did 1 Three bytes long Node ID
6-8 3 bytes (array uint8) did 2 Three bytes long Node ID
9-11 3 bytes (array uint8) did 3 Three bytes long Node ID

C Structure format

typedef struct SM_Protocol_CommandBlinkImmediately_s
{
    struct
    {
        uint8_t did[3];
        struct
        {
            uint8_t pattern : 6;    /** bits 0:5 */
            uint8_t brightness : 2; /** bits 6:7 */
        };

    } device[3];

} SM_Protocol_CommandBlinkImmediately_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 200, length = 12 */
0xc8, 0x0c, 0x00, 
/* Value buffer */

/* Device 0:
did 0 = [1, 2, 3],
brightness = 0x03;
pattern = 0x06;
*/
0x01, 0x02, 0x03, 0xc6, 

/* Device 1:
did 1 = [0, 0, 1],
brightness = 0x01;
pattern = 0x00;
cycleId = 2200;
*/
0x00, 0x00, 0x01, 0x40, 

/* Device 2:
did 2 = [0, 0, 0] - not used
*/
0x00, 0x00, 0x00, 0x00,
}

Frame transmitted from the PC to the device (Master Anchor). The request is used to turn on the application LEDs on one or more devices and configure their light blink parameters. The command executes immediately as soon as it reaches addressed devices.

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3 [bits 0-5] 6 bit enum pattern 0 6 bits long pattern ID [0-63]
3 [bits 6-7] 2 bit enum brightness 0 6 bits long brightness ID [0-3]
4-6 3 bytes (array uint8) did 1 Three bytes long Node ID
7 [bits 0-5] 6 bit enum pattern 1 6 bits long pattern ID [0-63]
7 [bits 6-7] 2 bit enum brightness 1 6 bits long brightness ID [0-3]
8-10 3 bytes (array uint8) did 2 Three bytes long Node ID
11 [bits 0-5] 6 bit enum pattern 2 6 bits long pattern ID [0-63]
11 [bits 6-7] 2 bit enum brightness 2 6 bits long brightness ID [0-3]

C Structure format

typedef struct SM_Protocol_CommandBlink_s
{
    struct
    {
        uint8_t did[3];
        struct
        {
            uint8_t pattern : 6;    /** bits 0:5 */
            uint8_t brightness : 2; /** bits 6:7 */
        };

        uint16_t cycleId;
    } device[2];

} SM_Protocol_CommandBlink_t;

Frame example

uint8_t rawData[] =
{
/* TLV header: type = 201, length = 12 */
0xc9, 0x0c, 0x00, 
/* Value buffer */

/* Device 0:
did 0 = [1, 2, 3],
brightness = 0x03;
pattern = 0x06;
cycleId = 2200;
*/

0x01, 0x02, 0x03, 0xc6, 0x98, 0x08, 

/* Device 1:
did 1 = [0, 0, 1],
brightness = 0x01;
pattern = 0x00;
cycleId = 2200;
*/
0x00, 0x00, 0x01, 0x40, 0x98, 0x08, 
}

Frame transmitted from the PC to the device (Master Anchor). The request is used to turn on the application LEDs on one or more devices and configure their light blink parameters. The command allows to synchronize LEDs enable time to the UWB network cycle.

Byte Storage Field Description
0-2 3 bytes (array uint8) did 0 Three bytes long Node ID
3 [bits 0-5] 6 bit enum pattern 0 6 bits long pattern ID [0-63]
3 [bits 6-7] 2 bit enum brightness 0 6 bits long brightness ID [0-3]
4-5 2 bytes (uint16) cycleId 0 ID of the cycle in which blink will be triggered
6-8 3 bytes (array uint8) did 1 Three bytes long Node ID
9 [bits 0-5] 6 bit enum pattern 1 6 bits long pattern ID [0-63]
9 [bits 6-7] 2 bit enum brightness 1 6 bits long brightness ID [0-3]
10-11 2 bytes (uint16) cycleId 1 ID of the cycle in which blink will be triggered

IMU Bit Stiching

18 Bits 16 Samples

Memory map size = 108 bytes

Offset [7] [6] [5] [4] [3] [2] [1] [0] Group
0 X0[7] X0[6] X0[5] X0[4] X0[3] X0[2] X0[1] X0[0] Samples
1 X0[15] X0[14] X0[13] X0[12] X0[11] X0[10] X0[9] X0[8] Samples
2 Y0[5] Y0[4] Y0[3] Y0[2] Y0[1] Y0[0] X0[17] X0[16] Samples
3 Y0[13] Y0[12] Y0[11] Y0[10] Y0[9] Y0[8] Y0[7] Y0[6] Samples
4 Z0[3] Z0[2] Z0[1] Z0[0] Y0[17] Y0[16] Y0[15] Y0[14] Samples
5 Z0[11] Z0[10] Z0[9] Z0[8] Z0[7] Z0[6] Z0[5] Z0[4] Samples
6 X1[1] X1[0] Z0[17] Z0[16] Z0[15] Z0[14] Z0[13] Z0[12] Samples
7 X1[9] X1[8] X1[7] X1[6] X1[5] X1[4] X1[3] X1[2] Samples
8 X1[17] X1[16] X1[15] X1[14] X1[13] X1[12] X1[11] X1[10] Samples
9 Y1[7] Y1[6] Y1[5] Y1[4] Y1[3] Y1[2] Y1[1] Y1[0] Samples
10 Y1[15] Y1[14] Y1[13] Y1[12] Y1[11] Y1[10] Y1[9] Y1[8] Samples
11 Z1[5] Z1[4] Z1[3] Z1[2] Z1[1] Z1[0] Y1[17] Y1[16] Samples
12 Z1[13] Z1[12] Z1[11] Z1[10] Z1[9] Z1[8] Z1[7] Z1[6] Samples
13 X2[3] X2[2] X2[1] X2[0] Z1[17] Z1[16] Z1[15] Z1[14] Samples
14 X2[11] X2[10] X2[9] X2[8] X2[7] X2[6] X2[5] X2[4] Samples
15 Y2[1] Y2[0] X2[17] X2[16] X2[15] X2[14] X2[13] X2[12] Samples
16 Y2[9] Y2[8] Y2[7] Y2[6] Y2[5] Y2[4] Y2[3] Y2[2] Samples
17 Y2[17] Y2[16] Y2[15] Y2[14] Y2[13] Y2[12] Y2[11] Y2[10] Samples
18 Z2[7] Z2[6] Z2[5] Z2[4] Z2[3] Z2[2] Z2[1] Z2[0] Samples
19 Z2[15] Z2[14] Z2[13] Z2[12] Z2[11] Z2[10] Z2[9] Z2[8] Samples
20 X3[5] X3[4] X3[3] X3[2] X3[1] X3[0] Z2[17] Z2[16] Samples
21 X3[13] X3[12] X3[11] X3[10] X3[9] X3[8] X3[7] X3[6] Samples
22 Y3[3] Y3[2] Y3[1] Y3[0] X3[17] X3[16] X3[15] X3[14] Samples
23 Y3[11] Y3[10] Y3[9] Y3[8] Y3[7] Y3[6] Y3[5] Y3[4] Samples
24 Z3[1] Z3[0] Y3[17] Y3[16] Y3[15] Y3[14] Y3[13] Y3[12] Samples
25 Z3[9] Z3[8] Z3[7] Z3[6] Z3[5] Z3[4] Z3[3] Z3[2] Samples
26 Z3[17] Z3[16] Z3[15] Z3[14] Z3[13] Z3[12] Z3[11] Z3[10] Samples
27 X4[7] X4[6] X4[5] X4[4] X4[3] X4[2] X4[1] X4[0] Samples
28 X4[15] X4[14] X4[13] X4[12] X4[11] X4[10] X4[9] X4[8] Samples
29 Y4[5] Y4[4] Y4[3] Y4[2] Y4[1] Y4[0] X4[17] X4[16] Samples
30 Y4[13] Y4[12] Y4[11] Y4[10] Y4[9] Y4[8] Y4[7] Y4[6] Samples
31 Z4[3] Z4[2] Z4[1] Z4[0] Y4[17] Y4[16] Y4[15] Y4[14] Samples
32 Z4[11] Z4[10] Z4[9] Z4[8] Z4[7] Z4[6] Z4[5] Z4[4] Samples
33 X5[1] X5[0] Z4[17] Z4[16] Z4[15] Z4[14] Z4[13] Z4[12] Samples
34 X5[9] X5[8] X5[7] X5[6] X5[5] X5[4] X5[3] X5[2] Samples
35 X5[17] X5[16] X5[15] X5[14] X5[13] X5[12] X5[11] X5[10] Samples
36 Y5[7] Y5[6] Y5[5] Y5[4] Y5[3] Y5[2] Y5[1] Y5[0] Samples
37 Y5[15] Y5[14] Y5[13] Y5[12] Y5[11] Y5[10] Y5[9] Y5[8] Samples
38 Z5[5] Z5[4] Z5[3] Z5[2] Z5[1] Z5[0] Y5[17] Y5[16] Samples
39 Z5[13] Z5[12] Z5[11] Z5[10] Z5[9] Z5[8] Z5[7] Z5[6] Samples
40 X6[3] X6[2] X6[1] X6[0] Z5[17] Z5[16] Z5[15] Z5[14] Samples
41 X6[11] X6[10] X6[9] X6[8] X6[7] X6[6] X6[5] X6[4] Samples
42 Y6[1] Y6[0] X6[17] X6[16] X6[15] X6[14] X6[13] X6[12] Samples
43 Y6[9] Y6[8] Y6[7] Y6[6] Y6[5] Y6[4] Y6[3] Y6[2] Samples
44 Y6[17] Y6[16] Y6[15] Y6[14] Y6[13] Y6[12] Y6[11] Y6[10] Samples
45 Z6[7] Z6[6] Z6[5] Z6[4] Z6[3] Z6[2] Z6[1] Z6[0] Samples
46 Z6[15] Z6[14] Z6[13] Z6[12] Z6[11] Z6[10] Z6[9] Z6[8] Samples
47 X7[5] X7[4] X7[3] X7[2] X7[1] X7[0] Z6[17] Z6[16] Samples
48 X7[13] X7[12] X7[11] X7[10] X7[9] X7[8] X7[7] X7[6] Samples
49 Y7[3] Y7[2] Y7[1] Y7[0] X7[17] X7[16] X7[15] X7[14] Samples
50 Y7[11] Y7[10] Y7[9] Y7[8] Y7[7] Y7[6] Y7[5] Y7[4] Samples
51 Z7[1] Z7[0] Y7[17] Y7[16] Y7[15] Y7[14] Y7[13] Y7[12] Samples
52 Z7[9] Z7[8] Z7[7] Z7[6] Z7[5] Z7[4] Z7[3] Z7[2] Samples
53 Z7[17] Z7[16] Z7[15] Z7[14] Z7[13] Z7[12] Z7[11] Z7[10] Samples
54 X8[7] X8[6] X8[5] X8[4] X8[3] X8[2] X8[1] X8[0] Samples
55 X8[15] X8[14] X8[13] X8[12] X8[11] X8[10] X8[9] X8[8] Samples
56 Y8[5] Y8[4] Y8[3] Y8[2] Y8[1] Y8[0] X8[17] X8[16] Samples
57 Y8[13] Y8[12] Y8[11] Y8[10] Y8[9] Y8[8] Y8[7] Y8[6] Samples
58 Z8[3] Z8[2] Z8[1] Z8[0] Y8[17] Y8[16] Y8[15] Y8[14] Samples
59 Z8[11] Z8[10] Z8[9] Z8[8] Z8[7] Z8[6] Z8[5] Z8[4] Samples
60 X9[1] X9[0] Z8[17] Z8[16] Z8[15] Z8[14] Z8[13] Z8[12] Samples
61 X9[9] X9[8] X9[7] X9[6] X9[5] X9[4] X9[3] X9[2] Samples
62 X9[17] X9[16] X9[15] X9[14] X9[13] X9[12] X9[11] X9[10] Samples
63 Y9[7] Y9[6] Y9[5] Y9[4] Y9[3] Y9[2] Y9[1] Y9[0] Samples
64 Y9[15] Y9[14] Y9[13] Y9[12] Y9[11] Y9[10] Y9[9] Y9[8] Samples
65 Z9[5] Z9[4] Z9[3] Z9[2] Z9[1] Z9[0] Y9[17] Y9[16] Samples
66 Z9[13] Z9[12] Z9[11] Z9[10] Z9[9] Z9[8] Z9[7] Z9[6] Samples
67 X10[3] X10[2] X10[1] X10[0] Z9[17] Z9[16] Z9[15] Z9[14] Samples
68 X10[11] X10[10] X10[9] X10[8] X10[7] X10[6] X10[5] X10[4] Samples
69 Y10[1] Y10[0] X10[17] X10[16] X10[15] X10[14] X10[13] X10[12] Samples
70 Y10[9] Y10[8] Y10[7] Y10[6] Y10[5] Y10[4] Y10[3] Y10[2] Samples
71 Y10[17] Y10[16] Y10[15] Y10[14] Y10[13] Y10[12] Y10[11] Y10[10] Samples
72 Z10[7] Z10[6] Z10[5] Z10[4] Z10[3] Z10[2] Z10[1] Z10[0] Samples
73 Z10[15] Z10[14] Z10[13] Z10[12] Z10[11] Z10[10] Z10[9] Z10[8] Samples
74 X11[5] X11[4] X11[3] X11[2] X11[1] X11[0] Z10[17] Z10[16] Samples
75 X11[13] X11[12] X11[11] X11[10] X11[9] X11[8] X11[7] X11[6] Samples
76 Y11[3] Y11[2] Y11[1] Y11[0] X11[17] X11[16] X11[15] X11[14] Samples
77 Y11[11] Y11[10] Y11[9] Y11[8] Y11[7] Y11[6] Y11[5] Y11[4] Samples
78 Z11[1] Z11[0] Y11[17] Y11[16] Y11[15] Y11[14] Y11[13] Y11[12] Samples
79 Z11[9] Z11[8] Z11[7] Z11[6] Z11[5] Z11[4] Z11[3] Z11[2] Samples
80 Z11[17] Z11[16] Z11[15] Z11[14] Z11[13] Z11[12] Z11[11] Z11[10] Samples
81 X12[7] X12[6] X12[5] X12[4] X12[3] X12[2] X12[1] X12[0] Samples
82 X12[15] X12[14] X12[13] X12[12] X12[11] X12[10] X12[9] X12[8] Samples
83 Y12[5] Y12[4] Y12[3] Y12[2] Y12[1] Y12[0] X12[17] X12[16] Samples
84 Y12[13] Y12[12] Y12[11] Y12[10] Y12[9] Y12[8] Y12[7] Y12[6] Samples
85 Z12[3] Z12[2] Z12[1] Z12[0] Y12[17] Y12[16] Y12[15] Y12[14] Samples
86 Z12[11] Z12[10] Z12[9] Z12[8] Z12[7] Z12[6] Z12[5] Z12[4] Samples
87 X13[1] X13[0] Z12[17] Z12[16] Z12[15] Z12[14] Z12[13] Z12[12] Samples
88 X13[9] X13[8] X13[7] X13[6] X13[5] X13[4] X13[3] X13[2] Samples
89 X13[17] X13[16] X13[15] X13[14] X13[13] X13[12] X13[11] X13[10] Samples
90 Y13[7] Y13[6] Y13[5] Y13[4] Y13[3] Y13[2] Y13[1] Y13[0] Samples
91 Y13[15] Y13[14] Y13[13] Y13[12] Y13[11] Y13[10] Y13[9] Y13[8] Samples
92 Z13[5] Z13[4] Z13[3] Z13[2] Z13[1] Z13[0] Y13[17] Y13[16] Samples
93 Z13[13] Z13[12] Z13[11] Z13[10] Z13[9] Z13[8] Z13[7] Z13[6] Samples
94 X14[3] X14[2] X14[1] X14[0] Z13[17] Z13[16] Z13[15] Z13[14] Samples
95 X14[11] X14[10] X14[9] X14[8] X14[7] X14[6] X14[5] X14[4] Samples
96 Y14[1] Y14[0] X14[17] X14[16] X14[15] X14[14] X14[13] X14[12] Samples
97 Y14[9] Y14[8] Y14[7] Y14[6] Y14[5] Y14[4] Y14[3] Y14[2] Samples
98 Y14[17] Y14[16] Y14[15] Y14[14] Y14[13] Y14[12] Y14[11] Y14[10] Samples
99 Z14[7] Z14[6] Z14[5] Z14[4] Z14[3] Z14[2] Z14[1] Z14[0] Samples
100 Z14[15] Z14[14] Z14[13] Z14[12] Z14[11] Z14[10] Z14[9] Z14[8] Samples
101 X15[5] X15[4] X15[3] X15[2] X15[1] X15[0] Z14[17] Z14[16] Samples
102 X15[13] X15[12] X15[11] X15[10] X15[9] X15[8] X15[7] X15[6] Samples
103 Y15[3] Y15[2] Y15[1] Y15[0] X15[17] X15[16] X15[15] X15[14] Samples
104 Y15[11] Y15[10] Y15[9] Y15[8] Y15[7] Y15[6] Y15[5] Y15[4] Samples
105 Z15[1] Z15[0] Y15[17] Y15[16] Y15[15] Y15[14] Y15[13] Y15[12] Samples
106 Z15[9] Z15[8] Z15[7] Z15[6] Z15[5] Z15[4] Z15[3] Z15[2] Samples
107 Z15[17] Z15[16] Z15[15] Z15[14] Z15[13] Z15[12] Z15[11] Z15[10] Samples

19 Bits 16 Samples

Memory map size = 114 bytes

Offset [7] [6] [5] [4] [3] [2] [1] [0] Group
0 X0[7] X0[6] X0[5] X0[4] X0[3] X0[2] X0[1] X0[0] Samples
1 X0[15] X0[14] X0[13] X0[12] X0[11] X0[10] X0[9] X0[8] Samples
2 Y0[4] Y0[3] Y0[2] Y0[1] Y0[0] X0[18] X0[17] X0[16] Samples
3 Y0[12] Y0[11] Y0[10] Y0[9] Y0[8] Y0[7] Y0[6] Y0[5] Samples
4 Z0[1] Z0[0] Y0[18] Y0[17] Y0[16] Y0[15] Y0[14] Y0[13] Samples
5 Z0[9] Z0[8] Z0[7] Z0[6] Z0[5] Z0[4] Z0[3] Z0[2] Samples
6 Z0[17] Z0[16] Z0[15] Z0[14] Z0[13] Z0[12] Z0[11] Z0[10] Samples
7 X1[6] X1[5] X1[4] X1[3] X1[2] X1[1] X1[0] Z0[18] Samples
8 X1[14] X1[13] X1[12] X1[11] X1[10] X1[9] X1[8] X1[7] Samples
9 Y1[3] Y1[2] Y1[1] Y1[0] X1[18] X1[17] X1[16] X1[15] Samples
10 Y1[11] Y1[10] Y1[9] Y1[8] Y1[7] Y1[6] Y1[5] Y1[4] Samples
11 Z1[0] Y1[18] Y1[17] Y1[16] Y1[15] Y1[14] Y1[13] Y1[12] Samples
12 Z1[8] Z1[7] Z1[6] Z1[5] Z1[4] Z1[3] Z1[2] Z1[1] Samples
13 Z1[16] Z1[15] Z1[14] Z1[13] Z1[12] Z1[11] Z1[10] Z1[9] Samples
14 X2[5] X2[4] X2[3] X2[2] X2[1] X2[0] Z1[18] Z1[17] Samples
15 X2[13] X2[12] X2[11] X2[10] X2[9] X2[8] X2[7] X2[6] Samples
16 Y2[2] Y2[1] Y2[0] X2[18] X2[17] X2[16] X2[15] X2[14] Samples
17 Y2[10] Y2[9] Y2[8] Y2[7] Y2[6] Y2[5] Y2[4] Y2[3] Samples
18 Y2[18] Y2[17] Y2[16] Y2[15] Y2[14] Y2[13] Y2[12] Y2[11] Samples
19 Z2[7] Z2[6] Z2[5] Z2[4] Z2[3] Z2[2] Z2[1] Z2[0] Samples
20 Z2[15] Z2[14] Z2[13] Z2[12] Z2[11] Z2[10] Z2[9] Z2[8] Samples
21 X3[4] X3[3] X3[2] X3[1] X3[0] Z2[18] Z2[17] Z2[16] Samples
22 X3[12] X3[11] X3[10] X3[9] X3[8] X3[7] X3[6] X3[5] Samples
23 Y3[1] Y3[0] X3[18] X3[17] X3[16] X3[15] X3[14] X3[13] Samples
24 Y3[9] Y3[8] Y3[7] Y3[6] Y3[5] Y3[4] Y3[3] Y3[2] Samples
25 Y3[17] Y3[16] Y3[15] Y3[14] Y3[13] Y3[12] Y3[11] Y3[10] Samples
26 Z3[6] Z3[5] Z3[4] Z3[3] Z3[2] Z3[1] Z3[0] Y3[18] Samples
27 Z3[14] Z3[13] Z3[12] Z3[11] Z3[10] Z3[9] Z3[8] Z3[7] Samples
28 X4[3] X4[2] X4[1] X4[0] Z3[18] Z3[17] Z3[16] Z3[15] Samples
29 X4[11] X4[10] X4[9] X4[8] X4[7] X4[6] X4[5] X4[4] Samples
30 Y4[0] X4[18] X4[17] X4[16] X4[15] X4[14] X4[13] X4[12] Samples
31 Y4[8] Y4[7] Y4[6] Y4[5] Y4[4] Y4[3] Y4[2] Y4[1] Samples
32 Y4[16] Y4[15] Y4[14] Y4[13] Y4[12] Y4[11] Y4[10] Y4[9] Samples
33 Z4[5] Z4[4] Z4[3] Z4[2] Z4[1] Z4[0] Y4[18] Y4[17] Samples
34 Z4[13] Z4[12] Z4[11] Z4[10] Z4[9] Z4[8] Z4[7] Z4[6] Samples
35 X5[2] X5[1] X5[0] Z4[18] Z4[17] Z4[16] Z4[15] Z4[14] Samples
36 X5[10] X5[9] X5[8] X5[7] X5[6] X5[5] X5[4] X5[3] Samples
37 X5[18] X5[17] X5[16] X5[15] X5[14] X5[13] X5[12] X5[11] Samples
38 Y5[7] Y5[6] Y5[5] Y5[4] Y5[3] Y5[2] Y5[1] Y5[0] Samples
39 Y5[15] Y5[14] Y5[13] Y5[12] Y5[11] Y5[10] Y5[9] Y5[8] Samples
40 Z5[4] Z5[3] Z5[2] Z5[1] Z5[0] Y5[18] Y5[17] Y5[16] Samples
41 Z5[12] Z5[11] Z5[10] Z5[9] Z5[8] Z5[7] Z5[6] Z5[5] Samples
42 X6[1] X6[0] Z5[18] Z5[17] Z5[16] Z5[15] Z5[14] Z5[13] Samples
43 X6[9] X6[8] X6[7] X6[6] X6[5] X6[4] X6[3] X6[2] Samples
44 X6[17] X6[16] X6[15] X6[14] X6[13] X6[12] X6[11] X6[10] Samples
45 Y6[6] Y6[5] Y6[4] Y6[3] Y6[2] Y6[1] Y6[0] X6[18] Samples
46 Y6[14] Y6[13] Y6[12] Y6[11] Y6[10] Y6[9] Y6[8] Y6[7] Samples
47 Z6[3] Z6[2] Z6[1] Z6[0] Y6[18] Y6[17] Y6[16] Y6[15] Samples
48 Z6[11] Z6[10] Z6[9] Z6[8] Z6[7] Z6[6] Z6[5] Z6[4] Samples
49 X7[0] Z6[18] Z6[17] Z6[16] Z6[15] Z6[14] Z6[13] Z6[12] Samples
50 X7[8] X7[7] X7[6] X7[5] X7[4] X7[3] X7[2] X7[1] Samples
51 X7[16] X7[15] X7[14] X7[13] X7[12] X7[11] X7[10] X7[9] Samples
52 Y7[5] Y7[4] Y7[3] Y7[2] Y7[1] Y7[0] X7[18] X7[17] Samples
53 Y7[13] Y7[12] Y7[11] Y7[10] Y7[9] Y7[8] Y7[7] Y7[6] Samples
54 Z7[2] Z7[1] Z7[0] Y7[18] Y7[17] Y7[16] Y7[15] Y7[14] Samples
55 Z7[10] Z7[9] Z7[8] Z7[7] Z7[6] Z7[5] Z7[4] Z7[3] Samples
56 Z7[18] Z7[17] Z7[16] Z7[15] Z7[14] Z7[13] Z7[12] Z7[11] Samples
57 X8[7] X8[6] X8[5] X8[4] X8[3] X8[2] X8[1] X8[0] Samples
58 X8[15] X8[14] X8[13] X8[12] X8[11] X8[10] X8[9] X8[8] Samples
59 Y8[4] Y8[3] Y8[2] Y8[1] Y8[0] X8[18] X8[17] X8[16] Samples
60 Y8[12] Y8[11] Y8[10] Y8[9] Y8[8] Y8[7] Y8[6] Y8[5] Samples
61 Z8[1] Z8[0] Y8[18] Y8[17] Y8[16] Y8[15] Y8[14] Y8[13] Samples
62 Z8[9] Z8[8] Z8[7] Z8[6] Z8[5] Z8[4] Z8[3] Z8[2] Samples
63 Z8[17] Z8[16] Z8[15] Z8[14] Z8[13] Z8[12] Z8[11] Z8[10] Samples
64 X9[6] X9[5] X9[4] X9[3] X9[2] X9[1] X9[0] Z8[18] Samples
65 X9[14] X9[13] X9[12] X9[11] X9[10] X9[9] X9[8] X9[7] Samples
66 Y9[3] Y9[2] Y9[1] Y9[0] X9[18] X9[17] X9[16] X9[15] Samples
67 Y9[11] Y9[10] Y9[9] Y9[8] Y9[7] Y9[6] Y9[5] Y9[4] Samples
68 Z9[0] Y9[18] Y9[17] Y9[16] Y9[15] Y9[14] Y9[13] Y9[12] Samples
69 Z9[8] Z9[7] Z9[6] Z9[5] Z9[4] Z9[3] Z9[2] Z9[1] Samples
70 Z9[16] Z9[15] Z9[14] Z9[13] Z9[12] Z9[11] Z9[10] Z9[9] Samples
71 X10[5] X10[4] X10[3] X10[2] X10[1] X10[0] Z9[18] Z9[17] Samples
72 X10[13] X10[12] X10[11] X10[10] X10[9] X10[8] X10[7] X10[6] Samples
73 Y10[2] Y10[1] Y10[0] X10[18] X10[17] X10[16] X10[15] X10[14] Samples
74 Y10[10] Y10[9] Y10[8] Y10[7] Y10[6] Y10[5] Y10[4] Y10[3] Samples
75 Y10[18] Y10[17] Y10[16] Y10[15] Y10[14] Y10[13] Y10[12] Y10[11] Samples
76 Z10[7] Z10[6] Z10[5] Z10[4] Z10[3] Z10[2] Z10[1] Z10[0] Samples
77 Z10[15] Z10[14] Z10[13] Z10[12] Z10[11] Z10[10] Z10[9] Z10[8] Samples
78 X11[4] X11[3] X11[2] X11[1] X11[0] Z10[18] Z10[17] Z10[16] Samples
79 X11[12] X11[11] X11[10] X11[9] X11[8] X11[7] X11[6] X11[5] Samples
80 Y11[1] Y11[0] X11[18] X11[17] X11[16] X11[15] X11[14] X11[13] Samples
81 Y11[9] Y11[8] Y11[7] Y11[6] Y11[5] Y11[4] Y11[3] Y11[2] Samples
82 Y11[17] Y11[16] Y11[15] Y11[14] Y11[13] Y11[12] Y11[11] Y11[10] Samples
83 Z11[6] Z11[5] Z11[4] Z11[3] Z11[2] Z11[1] Z11[0] Y11[18] Samples
84 Z11[14] Z11[13] Z11[12] Z11[11] Z11[10] Z11[9] Z11[8] Z11[7] Samples
85 X12[3] X12[2] X12[1] X12[0] Z11[18] Z11[17] Z11[16] Z11[15] Samples
86 X12[11] X12[10] X12[9] X12[8] X12[7] X12[6] X12[5] X12[4] Samples
87 Y12[0] X12[18] X12[17] X12[16] X12[15] X12[14] X12[13] X12[12] Samples
88 Y12[8] Y12[7] Y12[6] Y12[5] Y12[4] Y12[3] Y12[2] Y12[1] Samples
89 Y12[16] Y12[15] Y12[14] Y12[13] Y12[12] Y12[11] Y12[10] Y12[9] Samples
90 Z12[5] Z12[4] Z12[3] Z12[2] Z12[1] Z12[0] Y12[18] Y12[17] Samples
91 Z12[13] Z12[12] Z12[11] Z12[10] Z12[9] Z12[8] Z12[7] Z12[6] Samples
92 X13[2] X13[1] X13[0] Z12[18] Z12[17] Z12[16] Z12[15] Z12[14] Samples
93 X13[10] X13[9] X13[8] X13[7] X13[6] X13[5] X13[4] X13[3] Samples
94 X13[18] X13[17] X13[16] X13[15] X13[14] X13[13] X13[12] X13[11] Samples
95 Y13[7] Y13[6] Y13[5] Y13[4] Y13[3] Y13[2] Y13[1] Y13[0] Samples
96 Y13[15] Y13[14] Y13[13] Y13[12] Y13[11] Y13[10] Y13[9] Y13[8] Samples
97 Z13[4] Z13[3] Z13[2] Z13[1] Z13[0] Y13[18] Y13[17] Y13[16] Samples
98 Z13[12] Z13[11] Z13[10] Z13[9] Z13[8] Z13[7] Z13[6] Z13[5] Samples
99 X14[1] X14[0] Z13[18] Z13[17] Z13[16] Z13[15] Z13[14] Z13[13] Samples
100 X14[9] X14[8] X14[7] X14[6] X14[5] X14[4] X14[3] X14[2] Samples
101 X14[17] X14[16] X14[15] X14[14] X14[13] X14[12] X14[11] X14[10] Samples
102 Y14[6] Y14[5] Y14[4] Y14[3] Y14[2] Y14[1] Y14[0] X14[18] Samples
103 Y14[14] Y14[13] Y14[12] Y14[11] Y14[10] Y14[9] Y14[8] Y14[7] Samples
104 Z14[3] Z14[2] Z14[1] Z14[0] Y14[18] Y14[17] Y14[16] Y14[15] Samples
105 Z14[11] Z14[10] Z14[9] Z14[8] Z14[7] Z14[6] Z14[5] Z14[4] Samples
106 X15[0] Z14[18] Z14[17] Z14[16] Z14[15] Z14[14] Z14[13] Z14[12] Samples
107 X15[8] X15[7] X15[6] X15[5] X15[4] X15[3] X15[2] X15[1] Samples
108 X15[16] X15[15] X15[14] X15[13] X15[12] X15[11] X15[10] X15[9] Samples
109 Y15[5] Y15[4] Y15[3] Y15[2] Y15[1] Y15[0] X15[18] X15[17] Samples
110 Y15[13] Y15[12] Y15[11] Y15[10] Y15[9] Y15[8] Y15[7] Y15[6] Samples
111 Z15[2] Z15[1] Z15[0] Y15[18] Y15[17] Y15[16] Y15[15] Y15[14] Samples
112 Z15[10] Z15[9] Z15[8] Z15[7] Z15[6] Z15[5] Z15[4] Z15[3] Samples
113 Z15[18] Z15[17] Z15[16] Z15[15] Z15[14] Z15[13] Z15[12] Z15[11] Samples

11 Bits 16 Samples

Memory map size = 66 bytes

Offset [7] [6] [5] [4] [3] [2] [1] [0] Group
0 X0[7] X0[6] X0[5] X0[4] X0[3] X0[2] X0[1] X0[0] Samples
1 Y0[4] Y0[3] Y0[2] Y0[1] Y0[0] X0[10] X0[9] X0[8] Samples
2 Z0[1] Z0[0] Y0[10] Y0[9] Y0[8] Y0[7] Y0[6] Y0[5] Samples
3 Z0[9] Z0[8] Z0[7] Z0[6] Z0[5] Z0[4] Z0[3] Z0[2] Samples
4 X1[6] X1[5] X1[4] X1[3] X1[2] X1[1] X1[0] Z0[10] Samples
5 Y1[3] Y1[2] Y1[1] Y1[0] X1[10] X1[9] X1[8] X1[7] Samples
6 Z1[0] Y1[10] Y1[9] Y1[8] Y1[7] Y1[6] Y1[5] Y1[4] Samples
7 Z1[8] Z1[7] Z1[6] Z1[5] Z1[4] Z1[3] Z1[2] Z1[1] Samples
8 X2[5] X2[4] X2[3] X2[2] X2[1] X2[0] Z1[10] Z1[9] Samples
9 Y2[2] Y2[1] Y2[0] X2[10] X2[9] X2[8] X2[7] X2[6] Samples
10 Y2[10] Y2[9] Y2[8] Y2[7] Y2[6] Y2[5] Y2[4] Y2[3] Samples
11 Z2[7] Z2[6] Z2[5] Z2[4] Z2[3] Z2[2] Z2[1] Z2[0] Samples
12 X3[4] X3[3] X3[2] X3[1] X3[0] Z2[10] Z2[9] Z2[8] Samples
13 Y3[1] Y3[0] X3[10] X3[9] X3[8] X3[7] X3[6] X3[5] Samples
14 Y3[9] Y3[8] Y3[7] Y3[6] Y3[5] Y3[4] Y3[3] Y3[2] Samples
15 Z3[6] Z3[5] Z3[4] Z3[3] Z3[2] Z3[1] Z3[0] Y3[10] Samples
16 X4[3] X4[2] X4[1] X4[0] Z3[10] Z3[9] Z3[8] Z3[7] Samples
17 Y4[0] X4[10] X4[9] X4[8] X4[7] X4[6] X4[5] X4[4] Samples
18 Y4[8] Y4[7] Y4[6] Y4[5] Y4[4] Y4[3] Y4[2] Y4[1] Samples
19 Z4[5] Z4[4] Z4[3] Z4[2] Z4[1] Z4[0] Y4[10] Y4[9] Samples
20 X5[2] X5[1] X5[0] Z4[10] Z4[9] Z4[8] Z4[7] Z4[6] Samples
21 X5[10] X5[9] X5[8] X5[7] X5[6] X5[5] X5[4] X5[3] Samples
22 Y5[7] Y5[6] Y5[5] Y5[4] Y5[3] Y5[2] Y5[1] Y5[0] Samples
23 Z5[4] Z5[3] Z5[2] Z5[1] Z5[0] Y5[10] Y5[9] Y5[8] Samples
24 X6[1] X6[0] Z5[10] Z5[9] Z5[8] Z5[7] Z5[6] Z5[5] Samples
25 X6[9] X6[8] X6[7] X6[6] X6[5] X6[4] X6[3] X6[2] Samples
26 Y6[6] Y6[5] Y6[4] Y6[3] Y6[2] Y6[1] Y6[0] X6[10] Samples
27 Z6[3] Z6[2] Z6[1] Z6[0] Y6[10] Y6[9] Y6[8] Y6[7] Samples
28 X7[0] Z6[10] Z6[9] Z6[8] Z6[7] Z6[6] Z6[5] Z6[4] Samples
29 X7[8] X7[7] X7[6] X7[5] X7[4] X7[3] X7[2] X7[1] Samples
30 Y7[5] Y7[4] Y7[3] Y7[2] Y7[1] Y7[0] X7[10] X7[9] Samples
31 Z7[2] Z7[1] Z7[0] Y7[10] Y7[9] Y7[8] Y7[7] Y7[6] Samples
32 Z7[10] Z7[9] Z7[8] Z7[7] Z7[6] Z7[5] Z7[4] Z7[3] Samples
33 X8[7] X8[6] X8[5] X8[4] X8[3] X8[2] X8[1] X8[0] Samples
34 Y8[4] Y8[3] Y8[2] Y8[1] Y8[0] X8[10] X8[9] X8[8] Samples
35 Z8[1] Z8[0] Y8[10] Y8[9] Y8[8] Y8[7] Y8[6] Y8[5] Samples
36 Z8[9] Z8[8] Z8[7] Z8[6] Z8[5] Z8[4] Z8[3] Z8[2] Samples
37 X9[6] X9[5] X9[4] X9[3] X9[2] X9[1] X9[0] Z8[10] Samples
38 Y9[3] Y9[2] Y9[1] Y9[0] X9[10] X9[9] X9[8] X9[7] Samples
39 Z9[0] Y9[10] Y9[9] Y9[8] Y9[7] Y9[6] Y9[5] Y9[4] Samples
40 Z9[8] Z9[7] Z9[6] Z9[5] Z9[4] Z9[3] Z9[2] Z9[1] Samples
41 X10[5] X10[4] X10[3] X10[2] X10[1] X10[0] Z9[10] Z9[9] Samples
42 Y10[2] Y10[1] Y10[0] X10[10] X10[9] X10[8] X10[7] X10[6] Samples
43 Y10[10] Y10[9] Y10[8] Y10[7] Y10[6] Y10[5] Y10[4] Y10[3] Samples
44 Z10[7] Z10[6] Z10[5] Z10[4] Z10[3] Z10[2] Z10[1] Z10[0] Samples
45 X11[4] X11[3] X11[2] X11[1] X11[0] Z10[10] Z10[9] Z10[8] Samples
46 Y11[1] Y11[0] X11[10] X11[9] X11[8] X11[7] X11[6] X11[5] Samples
47 Y11[9] Y11[8] Y11[7] Y11[6] Y11[5] Y11[4] Y11[3] Y11[2] Samples
48 Z11[6] Z11[5] Z11[4] Z11[3] Z11[2] Z11[1] Z11[0] Y11[10] Samples
49 X12[3] X12[2] X12[1] X12[0] Z11[10] Z11[9] Z11[8] Z11[7] Samples
50 Y12[0] X12[10] X12[9] X12[8] X12[7] X12[6] X12[5] X12[4] Samples
51 Y12[8] Y12[7] Y12[6] Y12[5] Y12[4] Y12[3] Y12[2] Y12[1] Samples
52 Z12[5] Z12[4] Z12[3] Z12[2] Z12[1] Z12[0] Y12[10] Y12[9] Samples
53 X13[2] X13[1] X13[0] Z12[10] Z12[9] Z12[8] Z12[7] Z12[6] Samples
54 X13[10] X13[9] X13[8] X13[7] X13[6] X13[5] X13[4] X13[3] Samples
55 Y13[7] Y13[6] Y13[5] Y13[4] Y13[3] Y13[2] Y13[1] Y13[0] Samples
56 Z13[4] Z13[3] Z13[2] Z13[1] Z13[0] Y13[10] Y13[9] Y13[8] Samples
57 X14[1] X14[0] Z13[10] Z13[9] Z13[8] Z13[7] Z13[6] Z13[5] Samples
58 X14[9] X14[8] X14[7] X14[6] X14[5] X14[4] X14[3] X14[2] Samples
59 Y14[6] Y14[5] Y14[4] Y14[3] Y14[2] Y14[1] Y14[0] X14[10] Samples
60 Z14[3] Z14[2] Z14[1] Z14[0] Y14[10] Y14[9] Y14[8] Y14[7] Samples
61 X15[0] Z14[10] Z14[9] Z14[8] Z14[7] Z14[6] Z14[5] Z14[4] Samples
62 X15[8] X15[7] X15[6] X15[5] X15[4] X15[3] X15[2] X15[1] Samples
63 Y15[5] Y15[4] Y15[3] Y15[2] Y15[1] Y15[0] X15[10] X15[9] Samples
64 Z15[2] Z15[1] Z15[0] Y15[10] Y15[9] Y15[8] Y15[7] Y15[6] Samples
65 Z15[10] Z15[9] Z15[8] Z15[7] Z15[6] Z15[5] Z15[4] Z15[3] Samples

18 Bits 7 Samples

Memory map size = 48 bytes

Offset [7] [6] [5] [4] [3] [2] [1] [0] Group
0 X0[7] X0[6] X0[5] X0[4] X0[3] X0[2] X0[1] X0[0] Samples
1 X0[15] X0[14] X0[13] X0[12] X0[11] X0[10] X0[9] X0[8] Samples
2 Y0[5] Y0[4] Y0[3] Y0[2] Y0[1] Y0[0] X0[17] X0[16] Samples
3 Y0[13] Y0[12] Y0[11] Y0[10] Y0[9] Y0[8] Y0[7] Y0[6] Samples
4 Z0[3] Z0[2] Z0[1] Z0[0] Y0[17] Y0[16] Y0[15] Y0[14] Samples
5 Z0[11] Z0[10] Z0[9] Z0[8] Z0[7] Z0[6] Z0[5] Z0[4] Samples
6 X1[1] X1[0] Z0[17] Z0[16] Z0[15] Z0[14] Z0[13] Z0[12] Samples
7 X1[9] X1[8] X1[7] X1[6] X1[5] X1[4] X1[3] X1[2] Samples
8 X1[17] X1[16] X1[15] X1[14] X1[13] X1[12] X1[11] X1[10] Samples
9 Y1[7] Y1[6] Y1[5] Y1[4] Y1[3] Y1[2] Y1[1] Y1[0] Samples
10 Y1[15] Y1[14] Y1[13] Y1[12] Y1[11] Y1[10] Y1[9] Y1[8] Samples
11 Z1[5] Z1[4] Z1[3] Z1[2] Z1[1] Z1[0] Y1[17] Y1[16] Samples
12 Z1[13] Z1[12] Z1[11] Z1[10] Z1[9] Z1[8] Z1[7] Z1[6] Samples
13 X2[3] X2[2] X2[1] X2[0] Z1[17] Z1[16] Z1[15] Z1[14] Samples
14 X2[11] X2[10] X2[9] X2[8] X2[7] X2[6] X2[5] X2[4] Samples
15 Y2[1] Y2[0] X2[17] X2[16] X2[15] X2[14] X2[13] X2[12] Samples
16 Y2[9] Y2[8] Y2[7] Y2[6] Y2[5] Y2[4] Y2[3] Y2[2] Samples
17 Y2[17] Y2[16] Y2[15] Y2[14] Y2[13] Y2[12] Y2[11] Y2[10] Samples
18 Z2[7] Z2[6] Z2[5] Z2[4] Z2[3] Z2[2] Z2[1] Z2[0] Samples
19 Z2[15] Z2[14] Z2[13] Z2[12] Z2[11] Z2[10] Z2[9] Z2[8] Samples
20 X3[5] X3[4] X3[3] X3[2] X3[1] X3[0] Z2[17] Z2[16] Samples
21 X3[13] X3[12] X3[11] X3[10] X3[9] X3[8] X3[7] X3[6] Samples
22 Y3[3] Y3[2] Y3[1] Y3[0] X3[17] X3[16] X3[15] X3[14] Samples
23 Y3[11] Y3[10] Y3[9] Y3[8] Y3[7] Y3[6] Y3[5] Y3[4] Samples
24 Z3[1] Z3[0] Y3[17] Y3[16] Y3[15] Y3[14] Y3[13] Y3[12] Samples
25 Z3[9] Z3[8] Z3[7] Z3[6] Z3[5] Z3[4] Z3[3] Z3[2] Samples
26 Z3[17] Z3[16] Z3[15] Z3[14] Z3[13] Z3[12] Z3[11] Z3[10] Samples
27 X4[7] X4[6] X4[5] X4[4] X4[3] X4[2] X4[1] X4[0] Samples
28 X4[15] X4[14] X4[13] X4[12] X4[11] X4[10] X4[9] X4[8] Samples
29 Y4[5] Y4[4] Y4[3] Y4[2] Y4[1] Y4[0] X4[17] X4[16] Samples
30 Y4[13] Y4[12] Y4[11] Y4[10] Y4[9] Y4[8] Y4[7] Y4[6] Samples
31 Z4[3] Z4[2] Z4[1] Z4[0] Y4[17] Y4[16] Y4[15] Y4[14] Samples
32 Z4[11] Z4[10] Z4[9] Z4[8] Z4[7] Z4[6] Z4[5] Z4[4] Samples
33 X5[1] X5[0] Z4[17] Z4[16] Z4[15] Z4[14] Z4[13] Z4[12] Samples
34 X5[9] X5[8] X5[7] X5[6] X5[5] X5[4] X5[3] X5[2] Samples
35 X5[17] X5[16] X5[15] X5[14] X5[13] X5[12] X5[11] X5[10] Samples
36 Y5[7] Y5[6] Y5[5] Y5[4] Y5[3] Y5[2] Y5[1] Y5[0] Samples
37 Y5[15] Y5[14] Y5[13] Y5[12] Y5[11] Y5[10] Y5[9] Y5[8] Samples
38 Z5[5] Z5[4] Z5[3] Z5[2] Z5[1] Z5[0] Y5[17] Y5[16] Samples
39 Z5[13] Z5[12] Z5[11] Z5[10] Z5[9] Z5[8] Z5[7] Z5[6] Samples
40 X6[3] X6[2] X6[1] X6[0] Z5[17] Z5[16] Z5[15] Z5[14] Samples
41 X6[11] X6[10] X6[9] X6[8] X6[7] X6[6] X6[5] X6[4] Samples
42 Y6[1] Y6[0] X6[17] X6[16] X6[15] X6[14] X6[13] X6[12] Samples
43 Y6[9] Y6[8] Y6[7] Y6[6] Y6[5] Y6[4] Y6[3] Y6[2] Samples
44 Y6[17] Y6[16] Y6[15] Y6[14] Y6[13] Y6[12] Y6[11] Y6[10] Samples
45 Z6[7] Z6[6] Z6[5] Z6[4] Z6[3] Z6[2] Z6[1] Z6[0] Samples
46 Z6[15] Z6[14] Z6[13] Z6[12] Z6[11] Z6[10] Z6[9] Z6[8] Samples
47 --- --- --- --- --- --- Z6[17] Z6[16] Samples

19 Bits 7 Samples

Memory map size = 50 bytes

Offset [7] [6] [5] [4] [3] [2] [1] [0] Group
0 X0[7] X0[6] X0[5] X0[4] X0[3] X0[2] X0[1] X0[0] Samples
1 X0[15] X0[14] X0[13] X0[12] X0[11] X0[10] X0[9] X0[8] Samples
2 Y0[4] Y0[3] Y0[2] Y0[1] Y0[0] X0[18] X0[17] X0[16] Samples
3 Y0[12] Y0[11] Y0[10] Y0[9] Y0[8] Y0[7] Y0[6] Y0[5] Samples
4 Z0[1] Z0[0] Y0[18] Y0[17] Y0[16] Y0[15] Y0[14] Y0[13] Samples
5 Z0[9] Z0[8] Z0[7] Z0[6] Z0[5] Z0[4] Z0[3] Z0[2] Samples
6 Z0[17] Z0[16] Z0[15] Z0[14] Z0[13] Z0[12] Z0[11] Z0[10] Samples
7 X1[6] X1[5] X1[4] X1[3] X1[2] X1[1] X1[0] Z0[18] Samples
8 X1[14] X1[13] X1[12] X1[11] X1[10] X1[9] X1[8] X1[7] Samples
9 Y1[3] Y1[2] Y1[1] Y1[0] X1[18] X1[17] X1[16] X1[15] Samples
10 Y1[11] Y1[10] Y1[9] Y1[8] Y1[7] Y1[6] Y1[5] Y1[4] Samples
11 Z1[0] Y1[18] Y1[17] Y1[16] Y1[15] Y1[14] Y1[13] Y1[12] Samples
12 Z1[8] Z1[7] Z1[6] Z1[5] Z1[4] Z1[3] Z1[2] Z1[1] Samples
13 Z1[16] Z1[15] Z1[14] Z1[13] Z1[12] Z1[11] Z1[10] Z1[9] Samples
14 X2[5] X2[4] X2[3] X2[2] X2[1] X2[0] Z1[18] Z1[17] Samples
15 X2[13] X2[12] X2[11] X2[10] X2[9] X2[8] X2[7] X2[6] Samples
16 Y2[2] Y2[1] Y2[0] X2[18] X2[17] X2[16] X2[15] X2[14] Samples
17 Y2[10] Y2[9] Y2[8] Y2[7] Y2[6] Y2[5] Y2[4] Y2[3] Samples
18 Y2[18] Y2[17] Y2[16] Y2[15] Y2[14] Y2[13] Y2[12] Y2[11] Samples
19 Z2[7] Z2[6] Z2[5] Z2[4] Z2[3] Z2[2] Z2[1] Z2[0] Samples
20 Z2[15] Z2[14] Z2[13] Z2[12] Z2[11] Z2[10] Z2[9] Z2[8] Samples
21 X3[4] X3[3] X3[2] X3[1] X3[0] Z2[18] Z2[17] Z2[16] Samples
22 X3[12] X3[11] X3[10] X3[9] X3[8] X3[7] X3[6] X3[5] Samples
23 Y3[1] Y3[0] X3[18] X3[17] X3[16] X3[15] X3[14] X3[13] Samples
24 Y3[9] Y3[8] Y3[7] Y3[6] Y3[5] Y3[4] Y3[3] Y3[2] Samples
25 Y3[17] Y3[16] Y3[15] Y3[14] Y3[13] Y3[12] Y3[11] Y3[10] Samples
26 Z3[6] Z3[5] Z3[4] Z3[3] Z3[2] Z3[1] Z3[0] Y3[18] Samples
27 Z3[14] Z3[13] Z3[12] Z3[11] Z3[10] Z3[9] Z3[8] Z3[7] Samples
28 X4[3] X4[2] X4[1] X4[0] Z3[18] Z3[17] Z3[16] Z3[15] Samples
29 X4[11] X4[10] X4[9] X4[8] X4[7] X4[6] X4[5] X4[4] Samples
30 Y4[0] X4[18] X4[17] X4[16] X4[15] X4[14] X4[13] X4[12] Samples
31 Y4[8] Y4[7] Y4[6] Y4[5] Y4[4] Y4[3] Y4[2] Y4[1] Samples
32 Y4[16] Y4[15] Y4[14] Y4[13] Y4[12] Y4[11] Y4[10] Y4[9] Samples
33 Z4[5] Z4[4] Z4[3] Z4[2] Z4[1] Z4[0] Y4[18] Y4[17] Samples
34 Z4[13] Z4[12] Z4[11] Z4[10] Z4[9] Z4[8] Z4[7] Z4[6] Samples
35 X5[2] X5[1] X5[0] Z4[18] Z4[17] Z4[16] Z4[15] Z4[14] Samples
36 X5[10] X5[9] X5[8] X5[7] X5[6] X5[5] X5[4] X5[3] Samples
37 X5[18] X5[17] X5[16] X5[15] X5[14] X5[13] X5[12] X5[11] Samples
38 Y5[7] Y5[6] Y5[5] Y5[4] Y5[3] Y5[2] Y5[1] Y5[0] Samples
39 Y5[15] Y5[14] Y5[13] Y5[12] Y5[11] Y5[10] Y5[9] Y5[8] Samples
40 Z5[4] Z5[3] Z5[2] Z5[1] Z5[0] Y5[18] Y5[17] Y5[16] Samples
41 Z5[12] Z5[11] Z5[10] Z5[9] Z5[8] Z5[7] Z5[6] Z5[5] Samples
42 X6[1] X6[0] Z5[18] Z5[17] Z5[16] Z5[15] Z5[14] Z5[13] Samples
43 X6[9] X6[8] X6[7] X6[6] X6[5] X6[4] X6[3] X6[2] Samples
44 X6[17] X6[16] X6[15] X6[14] X6[13] X6[12] X6[11] X6[10] Samples
45 Y6[6] Y6[5] Y6[4] Y6[3] Y6[2] Y6[1] Y6[0] X6[18] Samples
46 Y6[14] Y6[13] Y6[12] Y6[11] Y6[10] Y6[9] Y6[8] Y6[7] Samples
47 Z6[3] Z6[2] Z6[1] Z6[0] Y6[18] Y6[17] Y6[16] Y6[15] Samples
48 Z6[11] Z6[10] Z6[9] Z6[8] Z6[7] Z6[6] Z6[5] Z6[4] Samples
49 --- Z6[18] Z6[17] Z6[16] Z6[15] Z6[14] Z6[13] Z6[12] Samples

11 Bits 7 Samples

Memory map size = 29 bytes

Offset [7] [6] [5] [4] [3] [2] [1] [0] Group
0 X0[7] X0[6] X0[5] X0[4] X0[3] X0[2] X0[1] X0[0] Samples
1 Y0[4] Y0[3] Y0[2] Y0[1] Y0[0] X0[10] X0[9] X0[8] Samples
2 Z0[1] Z0[0] Y0[10] Y0[9] Y0[8] Y0[7] Y0[6] Y0[5] Samples
3 Z0[9] Z0[8] Z0[7] Z0[6] Z0[5] Z0[4] Z0[3] Z0[2] Samples
4 X1[6] X1[5] X1[4] X1[3] X1[2] X1[1] X1[0] Z0[10] Samples
5 Y1[3] Y1[2] Y1[1] Y1[0] X1[10] X1[9] X1[8] X1[7] Samples
6 Z1[0] Y1[10] Y1[9] Y1[8] Y1[7] Y1[6] Y1[5] Y1[4] Samples
7 Z1[8] Z1[7] Z1[6] Z1[5] Z1[4] Z1[3] Z1[2] Z1[1] Samples
8 X2[5] X2[4] X2[3] X2[2] X2[1] X2[0] Z1[10] Z1[9] Samples
9 Y2[2] Y2[1] Y2[0] X2[10] X2[9] X2[8] X2[7] X2[6] Samples
10 Y2[10] Y2[9] Y2[8] Y2[7] Y2[6] Y2[5] Y2[4] Y2[3] Samples
11 Z2[7] Z2[6] Z2[5] Z2[4] Z2[3] Z2[2] Z2[1] Z2[0] Samples
12 X3[4] X3[3] X3[2] X3[1] X3[0] Z2[10] Z2[9] Z2[8] Samples
13 Y3[1] Y3[0] X3[10] X3[9] X3[8] X3[7] X3[6] X3[5] Samples
14 Y3[9] Y3[8] Y3[7] Y3[6] Y3[5] Y3[4] Y3[3] Y3[2] Samples
15 Z3[6] Z3[5] Z3[4] Z3[3] Z3[2] Z3[1] Z3[0] Y3[10] Samples
16 X4[3] X4[2] X4[1] X4[0] Z3[10] Z3[9] Z3[8] Z3[7] Samples
17 Y4[0] X4[10] X4[9] X4[8] X4[7] X4[6] X4[5] X4[4] Samples
18 Y4[8] Y4[7] Y4[6] Y4[5] Y4[4] Y4[3] Y4[2] Y4[1] Samples
19 Z4[5] Z4[4] Z4[3] Z4[2] Z4[1] Z4[0] Y4[10] Y4[9] Samples
20 X5[2] X5[1] X5[0] Z4[10] Z4[9] Z4[8] Z4[7] Z4[6] Samples
21 X5[10] X5[9] X5[8] X5[7] X5[6] X5[5] X5[4] X5[3] Samples
22 Y5[7] Y5[6] Y5[5] Y5[4] Y5[3] Y5[2] Y5[1] Y5[0] Samples
23 Z5[4] Z5[3] Z5[2] Z5[1] Z5[0] Y5[10] Y5[9] Y5[8] Samples
24 X6[1] X6[0] Z5[10] Z5[9] Z5[8] Z5[7] Z5[6] Z5[5] Samples
25 X6[9] X6[8] X6[7] X6[6] X6[5] X6[4] X6[3] X6[2] Samples
26 Y6[6] Y6[5] Y6[4] Y6[3] Y6[2] Y6[1] Y6[0] X6[10] Samples
27 Z6[3] Z6[2] Z6[1] Z6[0] Y6[10] Y6[9] Y6[8] Y6[7] Samples
28 --- Z6[10] Z6[9] Z6[8] Z6[7] Z6[6] Z6[5] Z6[4] Samples

Document revision

Unreleased

[0.11.0] - 2024-01-18

Added

[0.10.0] - 2023-12-20

Added

Changed

Fixed

[0.8.0] - 2023-11-27

Added

Removed

[0.7.1] - 2023-11-10

Added

[0.7.0] - 2023-10-30

Added

[0.6.1] - 2023-10-13

Added

Changed

[0.6.0] - 2023-10-04

Added

Changed

[0.5.0] - 2023-09-15

Changed

[0.4.0] - 2023-08-31

Added

[0.3.0] - 2023-08-23

Added

[0.2.0] - 2023-08-14

Fixed

Added

Changed

[0.1.0] - 2023-07-19

Initial document release - Partial description of the TLV protocol.

EXTRAS

Some C code to play with structures

#include <stdint.h>
#include <stdio.h>
#include <string.h>

#define TLV_HEADER_LENGTH 3u

typedef enum __attribute__((packed)) Protocol_FrameType_e
{
    /* Anchor -> PC*/
    Protocol_Frame_ToF                   = 0x01,
    Protocol_Frame_Serial                = 0x02,
    Protocol_Frame_AdminDistributionData = 0x03,
    Protocol_Frame_CompressedData        = 0x04,
    Protocol_Frame_AccelerometerData     = 0x05,
    Protocol_Frame_GyroscopeData         = 0x06,
    Protocol_Frame_MagnetometerData      = 0x07,
    Protocol_Frame_Sync_Blink            = 201,
    Protocol_Frame_Sync_Shutdown         = 140,
    Protocol_Frame_SetUWBConfig          = 139,

} Protocol_FrameType_t;

typedef struct __attribute__((packed)) Protocol_Frame_s
{
    uint8_t type;
    uint16_t length;
    uint8_t value[];

} Protocol_Frame_t;


typedef struct __attribute__((packed)) ToF_Tag_s
{
    uint8_t did[3];
    struct
    {
        uint8_t receivedByTag : 4;    /** bits 0:3 */
        uint8_t receivedByAnchor : 4; /** bits 4:7 */
    } rssi;

    uint16_t tof[];
} ToF_Tag_t;

typedef struct __attribute__((packed)) ToF_TagList_s
{
    struct
    {
        uint8_t numberOfToFs : 6; /** bits 0:5 */
        uint8_t precision : 2;    /** bits 6:7 */
    };

    uint8_t tagCount;
    uint8_t tagData[];

} ToF_TagList_t;

typedef struct __attribute__((packed)) Protocol_ToFReport_s
{
    uint8_t did[3];
    uint16_t cycleId;

    struct
    {
        uint8_t did[3];
        struct
        {
            uint8_t receivedByTag : 4;    /** bits 0:3 */
            uint8_t receivedByAnchor : 4; /** bits 4:7 */
        } rssi;

        uint16_t tof[4];
    } a2a;

    uint8_t tagListsCount;
    uint8_t tagListsData[];

} Protocol_ToFReport_t;

typedef struct __attribute__((packed)) Protocol_Sensors_s
{
    uint8_t did[3];
    uint16_t cycleId;
    uint8_t slotId;
    uint8_t data[];
} Protocol_Sensors_t;

typedef struct __attribute__((packed)) Protocol_AdminDistributionInfo_s
{
    uint8_t did[3];
    uint16_t cycleId;

    /* Constants */

    uint8_t apiVersion;
    uint8_t fwVersion;
    uint8_t hwid;
    uint8_t MAC[6];

    /* Config */
    struct
    {
        uint8_t deviceOffset;
        uint8_t frequency;
        uint8_t seat;
    } cycle;

    uint8_t serialNumber[4];
    char name[9];
    char group[3];
    uint8_t license[2];

    struct
    {
        uint8_t txPowerPreset;
    } bt;

    struct
    {
        uint8_t ch3AntennaDelay;
        uint8_t ch5AntennaDelay;
        uint8_t txPowerPreset;
    } uwb;

    struct
    {
        uint8_t boardConfig;
        uint8_t pressureCallibration;

        struct
        {
            uint8_t x;
            uint8_t y;
            uint8_t z;
        } magnetoBias;

        struct
        {
            uint8_t x;
            uint8_t y;
            uint8_t z;
        } magnetoScalar;

        struct
        {
            uint8_t x;
            uint8_t y;
            uint8_t z;
        } accelerometerBias;

    } sensorsConfig;

    /* Dynamic sensor data */
    struct
    {
        uint8_t vbat;
        uint8_t motionByte;
        uint8_t pressure;
        uint8_t heartRate;
        uint8_t mox;
    } sensorsData;

} Protocol_AdminDistributionInfo_t;

typedef struct __attribute__((packed)) SM_Protocol_CommandShutdown_s
{
    struct __attribute__((packed))
    {
        uint8_t did[3];
    } device[4];

} SM_Protocol_CommandShutdown_t;

typedef struct __attribute__((packed)) SM_Protocol_CommandBlink_s
{
    struct __attribute__((packed))
    {
        uint8_t did[3];
        struct
        {
            uint8_t pattern : 6;    /** bits 0:5 */
            uint8_t brightness : 2; /** bits 6:7 */
        };

        uint16_t cycleId;
    } device[2];

} SM_Protocol_CommandBlink_t;

typedef struct __attribute__((packed)) SM_Protocol_CommandSetSeatBasic_s
{
    struct __attribute__((packed))
    {
        uint8_t did[3];
        uint8_t seat;
    } device[3];

} SM_Protocol_CommandSetSeatBasic_t;

typedef struct __attribute__((packed)) SM_Protocol_CommandSetUWBConfig_s
{
    struct __attribute__((packed))
    {
        uint8_t did[3];
        int8_t ch3;
        int8_t ch5;
        uint8_t txPower;
    } device[2];

} SM_Protocol_CommandSetUWBConfig_t;

#define ARRAY_SIZE(type) (sizeof(type) / sizeof(type[0]))

uint32_t bitStitcher_compress(
    const int32_t* const input,
    uint32_t* const output,
    uint8_t length,
    uint8_t bitsPerSample,
    uint8_t initialOffset)
{
    const uint8_t outputBits = sizeof(*output) * 8u;
    const uint32_t valueMask = ~(-(1 << bitsPerSample));

    uint8_t bitsLeft    = outputBits - initialOffset;
    uint32_t* outputPtr = &output[0];
    for (uint8_t inputIdx = 0; inputIdx < length; ++inputIdx)
    {
        const uint32_t value = input[inputIdx] & valueMask;
        if (bitsLeft >= bitsPerSample)
        {
            *outputPtr |= value << (outputBits - bitsLeft);
            bitsLeft -= bitsPerSample;

            if (bitsLeft == 0)
            {
                ++outputPtr;
                bitsLeft = outputBits;
            }
        }
        else
        {
            const uint32_t part1Mask = ~(-(1 << bitsLeft));
            const uint32_t part1     = value & part1Mask;
            const uint32_t part2     = value >> bitsLeft;
            const uint8_t part2Bits  = bitsPerSample - bitsLeft;

            *outputPtr |= part1 << (outputBits - bitsLeft);
            ++outputPtr;
            *outputPtr |= part2;

            bitsLeft = outputBits - part2Bits;
        }
    }

    return (uint32_t)((uintptr_t)outputPtr - (uintptr_t)output)
           + (sizeof(*output) - (bitsLeft / 8u));
}

static void bitStitcher_helper_print(uint32_t* buffer, uint8_t length)
{
    printf("WORDS\n");
    for (uint8_t i = 0; i < length; ++i)
    {
        printf("%02d: ", i);
        for (int8_t j = 31; j >= 0; --j)
        {
            printf("%d", (buffer[i] >> j) & 0x01);
            if (j % 8 == 0)
            {
                printf(" ");
            }
        }

        printf("  |  0x%08x\n", buffer[i]);
    }
}

static void bitStitcher_helper_printBytes(uint8_t* buffer, uint8_t length)
{
    printf("BYTES\n");
    for (uint8_t i = 0; i < length; ++i)
    {
        printf("%02d: ", i);
        for (int8_t j = 7; j >= 0; --j)
        {
            printf("%d", (buffer[i] >> j) & 0x01);
        }

        printf("  |  0x%02x\n", buffer[i]);
    }
}

void print_raw(uint8_t* buffer, uint16_t size)
{
    Protocol_Frame_t* frame = (Protocol_Frame_t*)buffer;

    printf("/* TLV header: type = %u, length = %u */\n\r", frame->type, frame->length);
    printf("0x%02x, 0x%02x, 0x%02x, \n\r", buffer[0], buffer[1], buffer[2]);
    printf("/* Value buffer */\n\r");
    for (uint8_t i = TLV_HEADER_LENGTH; i < size;)
    {
        for (uint8_t j = 0; j < 8 && i < size; ++j, ++i)
        {
            printf("0x%02x, ", buffer[i]);
        }
        printf("\n\r");
    }
}

void test_tof(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_ToF;

    Protocol_ToFReport_t* value = (Protocol_ToFReport_t*)frame->value;

    value->did[0]  = 5;
    value->did[1]  = 10;
    value->did[2]  = 15;
    value->cycleId = 5000;

    /* There is only one A2A report */
    value->a2a.did[0]                = 20;
    value->a2a.did[1]                = 40;
    value->a2a.did[2]                = 60;
    value->a2a.rssi.receivedByAnchor = 5;
    value->a2a.rssi.receivedByTag    = 12;
    value->a2a.tof[0]                = 300;
    value->a2a.tof[1]                = 302;
    value->a2a.tof[2]                = 301;
    value->a2a.tof[3]                = 303;

    value->tagListsCount = 1;

    /* Fill tag lists */
    ToF_TagList_t* taglist0 = (ToF_TagList_t*)value->tagListsData;
    taglist0->numberOfToFs  = 3;
    taglist0->precision     = 0;
    taglist0->tagCount      = 2;

    /* Size Helpers */
    const size_t headerSize = sizeof(value->a2a) + sizeof(value->cycleId)
                              + sizeof(value->did) + sizeof(value->tagListsCount);

    const size_t list0TagSize =
        sizeof(((ToF_Tag_t*)0)->did) + sizeof(((ToF_Tag_t*)0)->rssi)
        + (taglist0->numberOfToFs * (sizeof(((ToF_Tag_t*)0)->tof[0])));

    const size_t list0Size = sizeof(uint8_t) + sizeof(((ToF_TagList_t*)0)->tagCount)
                             + taglist0->tagCount * list0TagSize;

    /* Fill Tags */
    ToF_Tag_t* tag0 = (ToF_Tag_t*)&taglist0->tagData[0 * list0TagSize];

    tag0->did[0]                = 33;
    tag0->did[1]                = 34;
    tag0->did[2]                = 35;
    tag0->rssi.receivedByAnchor = 10;
    tag0->rssi.receivedByTag    = 12;
    tag0->tof[0]                = 200;
    tag0->tof[1]                = 201;
    tag0->tof[2]                = 202;

    ToF_Tag_t* tag1 = (ToF_Tag_t*)&taglist0->tagData[1 * list0TagSize];

    tag1->did[0]                = 33;
    tag1->did[1]                = 34;
    tag1->did[2]                = 36;
    tag1->rssi.receivedByAnchor = 11;
    tag1->rssi.receivedByTag    = 13;
    tag1->tof[0]                = 204;
    tag1->tof[1]                = 205;
    tag1->tof[2]                = 206;

    frame->length = headerSize + list0Size;
    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_sensors(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_Serial;


    Protocol_Sensors_t* value = (Protocol_Sensors_t*)frame->value;
    value->did[0]             = 10;
    value->did[1]             = 20;
    value->did[2]             = 30;
    value->cycleId            = 10000;
    value->slotId             = 50;

    sprintf(value->data, "AIRTLS");


    frame->length = sizeof(Protocol_Sensors_t) + strlen(value->data);

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_compressedData(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_CompressedData;


    Protocol_Sensors_t* value = (Protocol_Sensors_t*)frame->value;
    value->did[0]             = 10;
    value->did[1]             = 20;
    value->did[2]             = 30;
    value->cycleId            = 10000;
    value->slotId             = 50;

    sprintf(value->data, "AIRTLS");

    for (uint8_t i = 0; i < 100; ++i)
    {
        value->data[i] = i;
    }

    frame->length = sizeof(Protocol_Sensors_t) + 100;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_accelerometerData(void)
{
    // clang-format off
    static const int32_t samples[] = {
        -3044,      2329,        1406,
        -3054,      2335,        1427,
        -3048,      2329,        1420,
        -3066,      2283,        1467,
        -3059,      2262,        1454,
        -3085,      2270,        1471,
        -120064,    -131064,     130979,
        131070,     131069,      124216,
        -28471,     -130818,     63966,
        -3044,      2329,        1406,
        -3054,      2335,        1427,
        -3048,      2329,        1420,
        -3066,      2283,        1467,
        -3059,      2262,        1454,
        -3085,      2270,        1471,
        -3059,      2262,        1454,
    };
    // clang-format on

    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_AccelerometerData;


    Protocol_Sensors_t* value = (Protocol_Sensors_t*)frame->value;
    value->did[0]             = 10;
    value->did[1]             = 20;
    value->did[2]             = 30;
    value->cycleId            = 1234;
    value->slotId             = 77;

    uint8_t accelerometerDataSize =
        bitStitcher_compress(samples, value->data, ARRAY_SIZE(samples), 18, 8);

    frame->length = sizeof(Protocol_Sensors_t) + accelerometerDataSize;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_gyroscopeData(void)
{
    // clang-format off
    static const int32_t samples[] = {
        -647, -229, 427,
        -333, -229, 274,
        -374, -229, 427,
        -206, -167, 290,
        -390, -188, 290,
        -229, -251, 381,
        -354, -229, 381,
        -312, -229, 274,
        -167, -206, 290,
        -251, -229, 381,
        -229, -333, 274,
        -229, -374, 427,
        -188, -390, 290,
        -229, -354, 381,
        -229, -647, 427,
        -229, -312, 274
    };
    // clang-format on

    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_GyroscopeData;


    Protocol_Sensors_t* value = (Protocol_Sensors_t*)frame->value;
    value->did[0]             = 10;
    value->did[1]             = 20;
    value->did[2]             = 30;
    value->cycleId            = 4321;
    value->slotId             = 77;

    uint8_t accelerometerDataSize =
        bitStitcher_compress(samples, value->data, ARRAY_SIZE(samples), 19, 8);

    frame->length = sizeof(Protocol_Sensors_t) + accelerometerDataSize;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_magnetometerData(void)
{
    // clang-format off
    static const int32_t samples[] = {
        -248, -579, -425,
        -259, -580, -430,
        -258, -577, -429,
        -258, -577, -432,
        -257, -579, -432,
        -248, -578, -429,
        -259, -580, -425,
        -257, -578, -432,
        -259, -577, -430,
        -258, -580, -425,
        -257, -577, -432,
        -248, -579, -429,
        -259, -578, -430,
        -258, -577, -425,
        -248, -580, -432,
        -258, -578, -429
    };
    // clang-format on

    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_MagnetometerData;


    Protocol_Sensors_t* value = (Protocol_Sensors_t*)frame->value;
    value->did[0]             = 10;
    value->did[1]             = 20;
    value->did[2]             = 30;
    value->cycleId            = 1111;
    value->slotId             = 33;

    uint8_t accelerometerDataSize =
        bitStitcher_compress(samples, value->data, ARRAY_SIZE(samples), 11, 8);

    frame->length = sizeof(Protocol_Sensors_t) + accelerometerDataSize;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_adminDistribution(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_AdminDistributionData;
    frame->length           = sizeof(Protocol_AdminDistributionInfo_t);

    Protocol_AdminDistributionInfo_t* value =
        (Protocol_AdminDistributionInfo_t*)frame->value;

    value->did[0]     = 5;
    value->did[1]     = 10;
    value->did[2]     = 15;
    value->cycleId    = 7000;
    value->apiVersion = 1;
    value->fwVersion  = 2;
    value->hwid       = 3;

    value->MAC[0] = 0x11;
    value->MAC[1] = 0x12;
    value->MAC[2] = 0x13;
    value->MAC[3] = 0x14;
    value->MAC[4] = 0x15;
    value->MAC[5] = 0x16;

    value->serialNumber[0] = 1;
    value->serialNumber[1] = 0;
    value->serialNumber[2] = 0;
    value->serialNumber[3] = 0;

    value->license[0] = 221;
    value->license[1] = 222;

    value->cycle.deviceOffset                 = 0;
    value->cycle.frequency                    = 50;
    value->cycle.seat                         = 34;
    value->bt.txPowerPreset                   = 2;
    value->uwb.ch3AntennaDelay                = 99;
    value->uwb.ch5AntennaDelay                = 100;
    value->uwb.txPowerPreset                  = 1;
    value->sensorsConfig.boardConfig          = 0x00;
    value->sensorsConfig.pressureCallibration = 10;
    value->sensorsConfig.magnetoBias.x        = 7;
    value->sensorsConfig.magnetoBias.y        = 8;
    value->sensorsConfig.magnetoBias.z        = 9;
    value->sensorsConfig.magnetoScalar.x      = 4;
    value->sensorsConfig.magnetoScalar.y      = 5;
    value->sensorsConfig.magnetoScalar.z      = 6;
    value->sensorsConfig.accelerometerBias.x  = 1;
    value->sensorsConfig.accelerometerBias.y  = 2;
    value->sensorsConfig.accelerometerBias.z  = 3;
    value->sensorsData.vbat                   = 30;
    value->sensorsData.motionByte             = 1;
    value->sensorsData.pressure               = 98;
    value->sensorsData.heartRate              = 99;
    value->sensorsData.mox                    = 100;

    sprintf(value->name, "AIRTLS");
    sprintf(value->group, "AB");

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_shutdown(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_Sync_Shutdown;
    frame->length           = sizeof(SM_Protocol_CommandShutdown_t);

    SM_Protocol_CommandShutdown_t* value =
        (SM_Protocol_CommandShutdown_t*)frame->value;

    value->device[0].did[0] = 0x01;
    value->device[0].did[1] = 0x02;
    value->device[0].did[2] = 0x03;

    value->device[1].did[0] = 0x00;
    value->device[1].did[1] = 0x00;
    value->device[1].did[2] = 0x00;

    value->device[2].did[0] = 0x21;
    value->device[2].did[1] = 0x22;
    value->device[2].did[2] = 0x23;

    value->device[3].did[0] = 0x12;
    value->device[3].did[1] = 0x22;
    value->device[3].did[2] = 0x32;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);

}

void test_blink(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_Sync_Blink;
    frame->length           = sizeof(SM_Protocol_CommandBlink_t);

    SM_Protocol_CommandBlink_t* value =
        (SM_Protocol_CommandBlink_t*)frame->value;

    value->device[0].did[0] = 0x01;
    value->device[0].did[1] = 0x02;
    value->device[0].did[2] = 0x03;
    value->device[0].brightness = 0x03;
    value->device[0].pattern = 0x06;
    value->device[0].cycleId = 2200;

    value->device[1].did[0] = 0x00;
    value->device[1].did[1] = 0x00;
    value->device[1].did[2] = 0x00;
    value->device[1].brightness = 0x01;
    value->device[1].pattern = 0x00;
    value->device[1].cycleId = 2200;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_seatAllocation(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = 254;
    frame->length           = sizeof(SM_Protocol_CommandSetSeatBasic_t);

    SM_Protocol_CommandSetSeatBasic_t* value =
        (SM_Protocol_CommandSetSeatBasic_t*)frame->value;

    value->device[0].did[0] = 0x01;
    value->device[0].did[1] = 0x02;
    value->device[0].did[2] = 0x03;
    value->device[0].seat = 1;

    value->device[1].did[0] = 0x10;
    value->device[1].did[1] = 0x20;
    value->device[1].did[2] = 0x30;
    value->device[1].seat = 5;

    value->device[2].did[0] = 0x11;
    value->device[2].did[1] = 0x22;
    value->device[2].did[2] = 0x33;
    value->device[2].seat = 10;


    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

void test_setUWBConfig(void)
{
    uint8_t raw[1000] = {0};

    Protocol_Frame_t* frame = (Protocol_Frame_t*)raw;
    frame->type             = Protocol_Frame_SetUWBConfig;
    frame->length           = sizeof(SM_Protocol_CommandSetUWBConfig_t);

    SM_Protocol_CommandSetUWBConfig_t* value =
        (SM_Protocol_CommandSetUWBConfig_t*)frame->value;

    value->device[0].did[0] = 0x01;
    value->device[0].did[1] = 0x02;
    value->device[0].did[2] = 0x03;
    value->device[0].ch3 = -5;
    value->device[0].ch5 = 5;
    value->device[0].txPower = 1;

    value->device[1].did[0] = 0x10;
    value->device[1].did[1] = 0x20;
    value->device[1].did[2] = 0x30;
    value->device[1].ch3 = 10;
    value->device[1].ch5 = -10;
    value->device[1].txPower = 1;

    print_raw(raw, frame->length + TLV_HEADER_LENGTH);
}

int main()
{
    test_tof();
    test_sensors();
    test_adminDistribution();
    test_compressedData();
    test_accelerometerData();
    test_gyroscopeData();
    test_shutdown();
    test_blink();
    test_seatAllocation();
    test_setUWBConfig();

    return 0;
}

To play with raw data structures some C code was provided. It can be run in online GCC compiler:

www.onlinegdb.com

c