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[];
};
Type - A binary code, which indicates the kind of field that this part of the message represents
Length - The size of the value field (typically in bytes, or number of elements) To simplify frame processing (encoding/decoding) we can use constant size of 'length' field. Two bytes (uint16) is sufficient for us to encode all frames.
Value - Variable-sized series of bytes which contains data for this part of the message
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
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
length = 0x0003
Next 3 bytes 0x00, 0x01, 0x02
can be interpreted as A_t
structure, so
a1 = 0x00
a2 = 0x0201
But there is more data!
We need to repeat the whole process.
Take next byte 0x01,
and interpret it as message type.
type = 0x01
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,
.
length = 0x0008
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.
b1 = 0x0007
b2 = 'AIRTLS'
Dictionary
UWB - Ultra WideBand - Radio technology that can use a very low energy level for short-range, high-bandwidth communications over a large portion of the radio spectrum
ToF - Time of flight. Value represents time that signal traveled between devices. Expressed in DWT (DecaWaveTicks ⟶ 1DWT = 15.65ps). With ToF we can calculate distance between devices - 1DWT = 4.68mm
Tag - Device that we want to localize. Transmits sensors data to Anchors
Anchor - Device that calculates distance to Tag. Transmits collected distances to Master Anchor in Offload
Master Anchor - Main Anchor connected to PC. Gathers data from all Anchors and transmits them to the PC over USB, or Bluetooth LE
PC - Device that collects all system data and estimates Tag position basing on Tag⟷Anchor distances.
Cycle - Whole RTLS network works in cycle that consists on N time slots.
Slot - Fragment of RTLS network cycle that can be assigned to the device. Device can perform different operation in different time slots.
- TSYNC - Slot reserved for Anchors. Anchors transmits TSYNC messages that are responsible for network synchronization and configuration.
- TRESPONSE - Slot reserved for Tags. Tags transmits TRESPONSE messages that contains Tag status.
- OFFLOAD - Slot reserved for Anchors. Anchors transmits data collected during cycle to Master Anchor.
Motion Byte - 8 bits characterizing device movement
- bit 0-6 - dynamic range - 7 bit value of average acceleration vector:
range 0-59 - step 0.05g
range 60-127 - step 1g - bit 7 - device is facing up - Y Axis is above 45 degrees.
- bit 0-6 - dynamic range - 7 bit value of average acceleration vector:
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):
Protocol_ToFReport_t
- Top level structure. Contains fields that are present in every report and list ofToF_TagList_t
.ToF_TagList_t
- Middle level structure. Contains information about tags present in list (type, count), and list ofToF_Tag_t
.ToF_Tag_t
- Bottom level structure. Contains tag data (id, rssi and list of ToFs).
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).
- Protocol_ToFReport_t
- ToF_TagList_t [0]
- ToF_Tag_t [0]
- ToF_Tag_t [1]
- ToF_Tag_t [2]
- ToF_TagList_t [1]
- ToF_Tag_t [0]
- ToF_TagList_t [0]
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:
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:
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:
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:
- Seat number is absolute - first TSYNC seat is 0, first TRESPONSE seat is 15 (for 800us scheme).
- Seat number depends on selected cycle scheme.
- Command can allocate only TSYNC and TRESPONSE seats type.
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 |
0xC8 - Command Blink Immediately
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] |
0xC9 - Command Blink
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
- Set Network Delay command definition.
[0.10.0] - 2023-12-20
Added
- Added information about Anchor command queue implementation.
- Added information about
hwid
format now including chip type on highest 2 bits. - Set Random Period command definition.
Changed
- ACP Admin Info message has been extended to include list of slow update rate tags detected during active cycle.
Fixed
- Some minor inconsistencies found in example sections.
[0.8.0] - 2023-11-27
Added
- Factory Reset command definition.
- UWB TX Power command definition.
- Network Configuration command definition.
- Blink Immediately command definition.
Removed
- Seat allocation commands (deprecated in firmware).
[0.7.1] - 2023-11-10
Added
- Pressure and Pressure Calibration description.
[0.7.0] - 2023-10-30
Added
- Motion byte description.
- Settings for sleep control
[0.6.1] - 2023-10-13
Added
- Board config command.
- Fast seat allocation command.
Changed
- Minor editing improvements.
[0.6.0] - 2023-10-04
Added
- Impact data frame
- New BitStitching documentation
Changed
- BitStitching - No 8bit header in sensor samples
- Time of Flight (ToF) data frame - Added IMU data
- Admin distribution data frame - Added HIT field
[0.5.0] - 2023-09-15
Changed
- ToF offload structure - added extra A2A ToFs
[0.4.0] - 2023-08-31
Added
- Battery voltage units specification
- ACP Command set UWB config
- ACP Command set seat 25Hz
- ACP Command set seat 50Hz
[0.3.0] - 2023-08-23
Added
- ACP Command Blink
- ACP Command Shutdown (kill)
[0.2.0] - 2023-08-14
Fixed
- fixed inconsistency between
Admin Distribution Info
field description andProtocol_AdminDistributionInfo_t
structure layout in example section. The error was in field description section wherecycle
information should be placed just aftermac
field, followed byserialNumber
.
Added
- validity binary flag data to administration data offload
- unit specification for some of the fields
- RSSI unit specification in
Time of Flight
chapter - Sensor data frames
Changed
- firmware versioning in administration data offload (from api and firmware seprate values to firmware major and minor)
- UWB antenna delay type changed from unsigned to signed
[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: