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
{
/* --- Anchors --- */
/** Field anchor, mobile, LED */
Descriptor_BoardType_AIRTLS_FA01 = 0x04,
/** Field anchor nRF5340, mobile, LED */
Descriptor_BoardType_AIRTLS_FA02 = 0x07,
/** Anchor ETH/WiFi ESP32 nRF53 */
Descriptor_BoardType_AIRTLS_WA02 = 0x06,
/** Anchor Horn nRF53 */
Descriptor_BoardType_AIRTLS_HA02 = 0x24,
/** Anchor Socket Line-In Neutral-Out nRF53 */
Descriptor_BoardType_AIRTLS_LINO = 0x27,
/* --- Tags --- */
/** Tag Ball nRF52 */
Descriptor_BoardType_AIRTLS_TB0X = 0x3F,
/** Tag Display nRF52 */
Descriptor_BoardType_AIRTLS_TA01 = 0x3E,
/** Tag Display nRF53 */
Descriptor_BoardType_AIRTLS_TA02 = 0x37,
/** Tag Field Pylon nRF53*/
Descriptor_BoardType_AIRTLS_PT02 = 0x35,
/** Tag Industrial Ruggedized nRF53 */
Descriptor_BoardType_AIRTLS_CT02 = 0x33,
} 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 |
---|---|---|
0x04 | FA01 |
Field Anchor |
0x07 | FA02 |
Field Anchor (nRF53) |
0x06 | WA02 |
Anchor with Ethernet/WiFi interface |
0x24 | HA02 |
Horn Anchor |
0x27 | LINO |
Line-In Neutral-Out 230 VAC |
0x3F | TB0X |
Ball Tag |
0x3E | TA01 |
Display Tag (nRF52) |
0x37 | TA02 |
Display Tag (nRF53) |
0x35 | PT02 |
Pylon Tag |
0x33 | CT02 |
Industrial Tag |
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 |
0x80 (128) | PC ⟶ Master Anchor [⟶ UWB] | Command set serial number |
0x81 (129) | PC ⟶ Master Anchor [⟶ UWB] | Command set group |
0x82 (130) | PC ⟶ Master Anchor [⟶ UWB] | Command set name |
0x83 (131) | PC ⟶ Master Anchor [⟶ UWB] | Command set IMU calibration |
0x84 (132) | PC ⟶ Master Anchor [⟶ UWB] | Command set message |
0x85 (133) | PC ⟶ Master Anchor [⟶ UWB] | Command update license |
0x86 (134) | PC ⟶ Master Anchor [⟶ UWB] | Command set Magnetometer calibration |
0x87 (135) | PC ⟶ Master Anchor [⟶ UWB] | Command set Heart Rate MAC |
0x88 (136) | PC ⟶ Master Anchor [⟶ UWB] | Command set BLE config |
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 |
0x93 (147) | PC ⟶ Master Anchor [⟶ UWB] | Command display overlay command |
0x94 (148) | PC ⟶ Master Anchor [⟶ UWB] | Command display overlay update |
0x95 (149) | PC ⟶ Master Anchor [⟶ UWB] | Command display overlay upload |
0x96 (150) | PC ⟶ Master Anchor [⟶ UWB] | Command MOx setup |
0xB4 (180) | PC ⟶ Master Anchor [⟶ UWB] | Command set ESP config 1 |
0xB5 (181) | PC ⟶ Master Anchor [⟶ UWB] | Command set ESP config 2 |
0xB6 (182) | PC ⟶ Master Anchor [⟶ UWB] | Command set ESP WiFi password 1 |
0xB7 (183) | PC ⟶ Master Anchor [⟶ UWB] | Command set ESP WiFi password 2 |
0xC4 (196) | PC ⟶ Master Anchor [⟶ UWB] | Command commit seat plan |
0xC5 (197) | PC ⟶ Master Anchor [⟶ UWB] | Command set seat plan |
0xC6 (198) | PC ⟶ Master Anchor [⟶ UWB] | Command factory reset |
0xC7 (199) | PC ⟶ Master Anchor [⟶ UWB] | Command blink pylon |
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;
struct
{
/* Constants */
uint8_t fwVersionMajor;
uint8_t fwVersionMinor;
uint8_t hwid;
uint8_t mac[6];
/* Configuration */
struct
{
uint8_t deviceOffset;
uint8_t frequency;
uint8_t seat;
} cycle;
uint8_t serialNumber[4];
char name[9];
char group[3];
uint16_t licenseConfig;
struct
{
uint8_t txPowerPreset;
} bt;
struct
{
uint8_t txPowerPreset;
} uwb;
uint8_t boardConfig;
uint16_t licenseTime;
uint8_t seatPlanVersion;
} config;
/* Calibration data */
struct
{
struct
{
int8_t ch3AntennaDelay;
int8_t ch5AntennaDelay;
} uwb;
struct
{
uint8_t bias;
} pressure;
struct
{
struct
{
uint8_t x[2];
uint8_t y[2];
uint8_t z[2];
} bias;
struct
{
uint8_t x;
uint8_t y;
uint8_t z;
} scalar;
} magnetometer;
struct
{
struct
{
uint8_t x;
uint8_t y;
uint8_t z;
} accelerometer;
} imu;
} calibration;
/* 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 = 69 */
0x03, 0x45, 0x00,
/* Value buffer (Protocol_AdminDistributionInfo_t):
did = [0xaf, 0x31, 0x9e],
cycleId = 46385,
config.fwVersionMajor = 0,
config.fwVersionMinor = 13,
config.hwid = 124,
config.mac = [0xfd, 0x5d, 0x4b, 0xaf, 0x31, 0x9e],
config.cycle.deviceOffset = 0,
config.cycle.frequency = 5,
config.cycle.seat = 1,
config.serialNumber = [0x40, 0xE2, 0x01, 0x00],
config.name = "MY_TAG",
config.group = "ABC",
config.licenseConfig = 5,
config.bt.txPowerPreset = 0,
config.uwb.txPowerPreset = 22,
config.boardConfig = 0x00,
config.licenseTime = 0,
config.seatPlanVersion = 32,
calibration.uwb.ch3AntennaDelay = 0,
calibration.uwb.ch5AntennaDelay = 0,
calibration.pressure.bias = 255,
calibration.magnetometer.bias.x = 1,
calibration.magnetometer.bias.y = 2,
calibration.magnetometer.bias.z = 3,
calibration.magnetometer.scalar.x = 4,
calibration.magnetometer.scalar.y = 5,
calibration.magnetometer.scalar.z = 6,
calibration.imu.accelerometer.x = 9,
calibration.imu.accelerometer.y = 10,
calibration.imu.accelerometer.z = 11,
sensorsData.vbat = 255,
sensorsData.motionByte = 1,
sensorsData.hit = 255,
sensorsData.pressure = 98,
sensorsData.heartRate = 99,
sensorsData.mox = 100,
valid = [0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF],
slowTagsDetected = 0,
*/
0xAF, 0x31, 0x9E, 0x31, 0xB5
0x00, 0x0D, 0x7C, 0xFD, 0x5D, 0x4B, 0xAF, 0x31
0x9E, 0x00, 0x05, 0x01, 0x40, 0xE2, 0x01, 0x00
0x4D, 0x59, 0x5F, 0x54, 0x41, 0x47, 0x00, 0x00
0x00, 0x41, 0x42, 0x43, 0x05, 0x00, 0x00, 0x16
0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0xFF, 0x01
0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x05, 0x06
0x09, 0x0A, 0x0B, 0xFF, 0x01, 0xFF, 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) | config.fwVersionMajor |
Firmware version major number |
6 | 1 byte (uint8) | config.fwVersionMinor |
Firmware version minor number |
7 | 1 byte (uint8) | config.hwid |
Hardware ID with board type (6 bits) and chip type (highest 2 bits) |
8-13 | 6 bytes (array uint8) | config.mac |
48b MAC Address |
14 | 1 byte (uint8) | config.cycle.deviceOffset |
Cycle offset for low speed tags |
15 | 1 byte (uint8) | config.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) | config.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) | config.serialNumber |
4 Byte Serial number |
21-29 | 9 bytes (array char) | config.name |
Device name string |
30-32 | 3 bytes (array char) | config.group |
Device group name string |
33-34 | 2 bytes (uint16) | config.licenseConfig |
License configuration, applicable to display tags only: - bits 15:14 - failed activation attempts count (0-3) - bits 13:0 - total successful license activation count |
35 | 1 byte (uint8) | config.bt.txPowerPreset |
Bluetooth TX power preset, see here |
36 | 1 byte (uint8) | config.uwb.txPowerPreset |
UWB TX power in 0.5dB step in 0-30.5dB range. |
37 | 1 byte (uint8) | config.boardConfig |
Board config |
38-39 | 2 bytes (uint16) | config.licenseTime |
Remaining device license time in ticks (1 tick = 5 minutes), applicable to display tags only |
40 | 1 byte (uint8) | config.seatPlanVersion |
Version number of currently used seat plan. 0 Indicates default seat plan hardcoded in device firmware. Other value is provided by user during seat plan modification. |
41 | 1 byte (uint8) | calibration.uwb.ch3AntennaDelay |
UWB Antenna delay for UWB channel 1-3 - offset from default value. |
42 | 1 byte (uint8) | calibration.uwb.ch5AntennaDelay |
UWB Antenna delay for UWB channel 5 - offset from default value. |
43 | 1 byte (uint8) | calibration.pressure.bias |
Sensor calibration value which is substracted from the measured pressure value. |
44-45 | 2 byte (uint16) | calibration.magnetometer.bias.x |
Sensor calibration constant |
46-47 | 2 byte (uint16) | calibration.magnetometer.bias.y |
Sensor calibration constant |
48-49 | 2 byte (uint16) | calibration.magnetometer.bias.z |
Sensor calibration constant |
50 | 1 byte (uint8) | calibration.magnetometer.scalar.x |
Sensor calibration constant |
51 | 1 byte (uint8) | calibration.magnetometer.scalar.y |
Sensor calibration constant |
52 | 1 byte (uint8) | calibration.magnetometer.scalar.z |
Sensor calibration constant |
53 | 1 byte (uint8) | calibration.imu.accelerometer.x |
Sensor calibration constant |
54 | 1 byte (uint8) | calibration.imu.accelerometer.y |
Sensor calibration constant |
55 | 1 byte (uint8) | calibration.imu.accelerometer.z |
Sensor calibration constant |
56 | 1 byte (uint8) | sensorsData.vbat |
Battery voltage value encoded using following format: - minimum (binary 0) = 2754mV - maximum (binary 255) = 4250mV - resolution = ~5.84mV |
57 | 1 byte (uint8) | sensorsData.motionByte |
Motion byte characterizing device movement |
58 | 1 byte (uint8) | sensorsData.hit |
Impact hit detection in milliseconds relative to the start of the cycle. NOTE: It is "last known" impact value. |
59-67 | 9 bytes (array uint8) | sensorsData.platform |
Container for platform specific sensor measurements, see Platform specific Sensor Data table below for more information. |
68-75 | 8 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. |
76 | 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 |
Platform specific Sensor Data
Each type of platform in the system provides some custom sensor readings that are stored in the same place inside Admin Distribution record.
Display Tag
Byte | Storage | Field | Description |
---|---|---|---|
0 | 1 byte (uint8) | heartRate |
Heart Rate sensor value - pulse in BPM. |
1-3 | 3 bytes (struct) | mox |
Muscle Oxygenation sensor value. First 12 bits of the structure refer to raw ADC reading from first sensor, last 12 bits - raw ADC reading from the second sensor. ADC is configured to 12 bit resolution, Vref = 0.6 V, input gain = 1/6. Measured voltage can be calculated as: V = (reading * Vref)/(2^resolution * gain) Which, for given values, simplifies to: V = (reading * 3.6) / 4096 |
3-8 | - | Reserved for future use | - |
Ball Tag
Byte | Storage | Field | Description |
---|---|---|---|
0 | 1 byte (uint8) | pressure |
Pressure sensor value encoded using following format: - minimum (binary 0) = atmospheric pressure - maximum (binary 255) = 1.1 Bar above atmospheric pressure - resolution = ~4.3mBar Presented value already takes into account pressureCalibration value, so no additional calculations are required. |
1-8 | - | Reserved for future use | - |
Anchor
Byte | Storage | Field | Description |
---|---|---|---|
0-8 | - | Reserved for future use | - |
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,
};
Message contains packed accelerometer samples collected by the source device in cycle previous to the one at which data is received. Frame transmitted from the device (Master Anchor) to the PC after reception of tag response frame form the source 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 minimum.
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
};
Message contains packed gyroscope samples collected by the source device in cycle previous to the one at which data is received. Frame transmitted from the device (Master Anchor) to the PC after reception of tag response frame form the source 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 |
Data array contains bit-stitched set of gyroscope samples. Each sample is 19 bit signed int. Bit-stitching was implemented to increase the capacity of communication interface. It reduces number of unused bits to minimum.
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
};
Message contains packed magnetometer samples collected by the source device in cycle previous to the one at which data is received. Frame transmitted from the device (Master Anchor) to the PC after reception of tag response frame form the source 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 |
Data array contains bit-stitched set of magnetometer samples. Each sample is 11 bit signed int. Bit-stitching was implemented to increase the capacity of communication interface. It reduces number of unused bits to minimum.
Magnetometer data format:
0x08 - Impact sensor data
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 */
0x08, 0x48, 0x00,
/* Value buffer
did = [10, 20, 30],
cycleId = 1111,
slotId = 33
*/
0x0a, 0x14, 0x1e, 0x57, 0x04, 0x21,
/* Impact Data:
ht - Hit Type = 1 (Full)
hpos - Hit Position = 32 (ms)
hval - Hit Vector = 0xBBAA -> 48042
*/
0x41, 0xAA, 0xBB,
};
Message contains impact event description data determined by the source device in cycle previous to the one at which data is received. Frame transmitted from the device (Master Anchor) to the PC after reception of tag response frame form the source 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 (bit 0) | 1 bit | ht |
Type of the hit descriptor: 1 = Full 16-bit hit vector value, 0 = Reduced 8-bit hit vector value |
6 (bits 1:7) | 7 bits | hpos |
Hit position - offset of impact detection in milliseconds since the cycle beginning |
7-(8) | 1 or 2 bytes | hval |
Hit vector value - accelerometer output vector length for the sample collected at the moment of impact. Full measurement resolution is 64G, unit value depends on underlying type width (8 or 16-bits). |
0x80 - Command Set Serial
C Structure format
typedef struct SM_Protocol_CommandSetSerial_s
{
uint8_t did[3];
uint32_t serial;
uint8_t padding[5];
} SM_Protocol_CommandSetSerial_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 128, length = 12 */
0x80, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
serial = 0x3412CDAB
*/
0x01, 0x02, 0x03, 0xAB, 0xCD, 0x12, 0x34,
/* Padding
*/
0x00, 0x00, 0x00, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to change device serial number.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-6 | 4 bytes (uint32) | serial |
Serial number |
7-11 | 5 bytes (array uint8) | padding |
Command padding, unused |
0x81 - Command Set Group
C Structure format
typedef struct SM_Protocol_CommandSetGroup_s
{
struct
{
uint8_t did[3];
uint8_t group[3];
} devices[2];
} SM_Protocol_CommandSetGroup_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 129, length = 12 */
0x81, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did 0 = [1, 2, 3],
group 0 = 'ABC'
*/
0x01, 0x02, 0x03, 0x41, 0x42, 0x43,
/* Device 1:
did 1 = [255, 254, 253],
group 1 = 'DEF'
*/
0xFF, 0xFE, 0xFD, 0x44, 0x45, 0x46,
};
Frame transmitted from the PC to the device (Master Anchor) to change device logical group name.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did 0 |
Three bytes long Node ID |
3-5 | 3 bytes (array uint8) | group 0 |
Device group name, UTF-8 encoded, NULL termination not required |
6-8 | 3 bytes (array uint8) | did 1 |
Three bytes long Node ID |
9-11 | 3 bytes (array uint8) | group 1 |
Device group name, UTF-8 encoded, NULL termination not required |
0x82 - Command Set Name
C Structure format
typedef struct SM_Protocol_CommandSetName_s
{
uint8_t did[3];
uint8_t name[9];
} SM_Protocol_CommandSetName_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 130, length = 12 */
0x82, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
name = 'ABCDEF'
*/
0x01, 0x02, 0x03, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to change device logical name.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-11 | 9 bytes (array uint8) | name |
Device logical name, UTF-8 encoded, NULL termination not required |
0x83 - Command Set IMU Calibration
C Structure format
typedef struct SM_Protocol_CommandSetCalibrationIMU_s
{
struct
{
uint8_t did[3];
/** Accelerometer zero offset compensation */
uint8_t accelerometerBias[3];
} devices[2];
} SM_Protocol_CommandSetCalibrationIMU_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 131, length = 12 */
0x83, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did1 = [1, 2, 3],
accelerometerBias = [4, 5, 6]
*/
0x01, 0x02, 0x03, 0x04, 0x05, 0x06,
/* Device 1:
did2 = [7, 8, 9],
accelerometerBias = [10, 11, 12]
*/
0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C,
};
Frame transmitted from the PC to the device (Master Anchor) to upload IMU calibration constants. The coefficients are not used during signal acquisition. This is just a storage than can be used by software to store and retrieve calibration data unique for the device.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did1 |
Three bytes long Node ID |
3-5 | 3 bytes (array uint8) | accelerometer bias |
Accelerometer bias calibration constants per X, Y, Z axis |
6-8 | 3 bytes (array uint8) | did2 |
Three bytes long Node ID |
9-11 | 3 bytes (array uint8) | accelerometer bias |
Accelerometer bias calibration constants per X, Y, Z axis |
0x84 - Command Set Message
C Structure format
typedef struct SM_Protocol_CommandSetMessage_s
{
uint8_t did[3];
uint8_t message[9];
} SM_Protocol_CommandSetMessage_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 132, length = 12 */
0x84, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
message = 'ABCDEF'
*/
0x01, 0x02, 0x03, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x00, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to notify target display tag with custom short message.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-11 | 9 bytes (array uint8) | message |
Custom text message, UTF-8 encoded, NULL termination not required |
0x85 - Command Update License
C Structure format
typedef struct SM_Protocol_CommandUpdateLicense_s
{
SM_Protocol_DID_t did;
uint8_t licenseKey[8];
int8_t tickUpdate;
} SM_Protocol_CommandUpdateLicense_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 133, length = 12 */
0x85, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
licenseKey = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01, 0x02],
tickUpdate = 10,
*/
0x01, 0x02, 0x03, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x01, 0x02, 0x0A,
};
Frame transmitted from the PC to the device (Master Anchor) to update high update frequency license period for selected display tag.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-10 | 8 bytes (array uint8) | licenseKey |
License key used to authorize update request |
11 | 1 byte | tickUpdate |
Number of license ticks add or removed from the target device |
0x86 - Command Set Magnetometer Calibration
C Structure format
typedef struct SM_Protocol_CommandSetCalibrationMagnetometer_s
{
uint8_t did[3];
struct
{
/** Magnetometer zero offset compensation */
int16_t magnetometerBias[3];
/** Magnetometer gain skew compensation */
uint8_t magnetometerScalar[3];
} calibration;
} SM_Protocol_CommandSetCalibrationMagnetometer_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 134, length = 12 */
0x86, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
magnetometer bias = [4, 5, 6]
magnetometer scalar = [10, 11, 12]
*/
0x01, 0x02, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x0A, 0x0B, 0x0C
};
Frame transmitted from the PC to the device (Master Anchor) to upload Magnetometer calibration constants. The coefficients are not used during signal acquisition. This is just a storage than can be used by software to store and retrieve calibration data unique for the device.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-8 | 6 bytes (array uint16) | magnetometer bias |
Magnetometer bias calibration constants per X, Y, Z axis |
9-11 | 3 bytes (array uint8) | magnetometer scalar |
Magnetometer scalar/gain calibration constants per X, Y, Z axis |
0x87 - Command Set Heart Rate MAC
C Structure format
typedef struct SM_Protocol_CommandSetHeartRateMAC_s
{
uint8_t did[3];
/** MAC address for the paired HR belt, ordered from the MSB */
uint8_t mac[6];
/** Unused command padding */
uint8_t padding[3];
} SM_Protocol_CommandSetHeartRateMAC_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 135, length = 12 */
0x87, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
mac = [0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF]
padding = [0, 0, 0]
*/
0x01, 0x02, 0x03, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x00, 0x00
};
Frame transmitted from the PC to the device (Master Anchor) to set Heart Rate belt MAC address that will be monitored for BPM by the target Tag Device. Settings will be synced (saved in non-volatile memory) 3000ms after processing of the command.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-8 | 6 bytes (array uint8) | mac |
Heart Rate belt MAC address |
9-11 | 3 bytes (array uint8) | padding |
Unused command padding |
0x88 - Command Set BLE Config
C Structure format
typedef struct SM_Protocol_CommandSetBLEConfig_s
{
struct
{
uint8_t did[3];
uint8_t txPower;
} device[3];
} SM_Protocol_CommandSetBLEConfig_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 136, length = 12 */
0x88, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did 0 = [1, 2, 3],
txPower = 1
*/
0x01, 0x02, 0x03, 0x01,
/* Device 1:
did 0 = [16, 32, 48],
txPower = 1
*/
0x10, 0x20, 0x30, 0x01,
/* Device 2:
did 0 = [0, 0, 0],
txPower = 0
*/
0x10, 0x20, 0x30, 0x01,
};
Frame transmitted from the PC to the device (Master Anchor) to change BLE configuration. BLE settings will be synced (saved in non-volatile memory) 3000ms 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 (uint8) | txPower 0 |
BLE TX power profile encoded using following format: - 0 = -20 dB - 1 = -16 dB - 2 = -12 dB - 3 = -8 dB - 4 = -4 dB - 5 = 0 dB - 6 = 4 dB (only nRF52) - 7 = 8 dB (only nRF52) |
4-6 | 3 bytes (array uint8) | did 1 |
Three bytes long Node ID |
7 | 1 byte (uint8) | txPower 1 |
BLE TX power profile encoded using following format: - 0 = -20 dB - 1 = -16 dB - 2 = -12 dB - 3 = -8 dB - 4 = -4 dB - 5 = 0 dB - 6 = 4 dB (only nRF52) - 7 = 8 dB (only nRF52) |
8-10 | 3 bytes (array uint8) | did 2 |
Three bytes long Node ID |
11 | 1 byte (uint8) | txPower 2 |
BLE TX power profile encoded using following format: - 0 = -20 dB - 1 = -16 dB - 2 = -12 dB - 3 = -8 dB - 4 = -4 dB - 5 = 0 dB - 6 = 4 dB (only nRF52) - 7 = 8 dB (only nRF52) |
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.
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. |
3 | wake charging on/off |
Controls whether the device when put into sleep mode and actively charging can be enabled using Wake On Motion functionality, 0: off, 1: on. |
4 | haptic on/off |
Controls whether haptic vibration notifications are generated by a display tag on some events (e.g. message reception), 0: off, 1: on. |
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 Sniffer
- 5 Juggler
- 6-7 Reserved */
uint8_t anchorSeatPool : 1; /** bits 5 Anchor seat pool to use:
- 0 standard pool
- 1 offloadless pool
*/
uint8_t reserved : 2; /** bits 6: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
anchor pool = Standard
*/
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
anchor pool = Offloadless
*/
0x10, 0x20, 0x30, 0x05, 0x05, 0x21,
};
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 21 (for default 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 - 10 - 175Hz |
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 - 4 - sniffer - 5 - juggler |
5 [bit 5] | 1 bit enum | anchor pool 0 |
Anchor seat pool to use: - 0 - Standard - 1 - Offloadless |
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.
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.
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 |
0x93 - Command Display Overlay Command
C Structure format
typedef struct SM_Protocol_CommandDisplayOverlayCommand_s
{
struct
{
/** Device ID */
uint8_t did[3];
/** Overlay command */
uint8_t command;
/** Overlay command parameters */
uint8_t parameters[2];
} device[2];
} SM_Protocol_CommandDisplayOverlayCommand_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 147, length = 12 */
0x93, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did 0 = [1, 2, 3],
command = 1
parameters = [4, 5]
*/
0x01, 0x02, 0x03, 0x01, 0x04, 0x05,
/* Device 1:
did 1 = [7, 8, 9],
command = 2
parameters = [0, 0]
*/
0x07, 0x08, 0x09, 0x02, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to relay command to target display tags, which should execute given overlay commands upon frame reception.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did 0 |
Three bytes long Node ID |
3 | byte (uint8) | command |
Display overlay command |
4-5 | 2 bytes (array uint8) | parameters |
Display overlay command specific paramaters |
6-8 | 3 bytes (array uint8) | did 1 |
Three bytes long Node ID |
9 | byte (uint8) | command |
Display overlay command |
10-11 | 2 bytes (array uint8) | parameters |
Display overlay command specific paramaters |
Supported commands:
Command | Parameter 1 | Parameter 2 | Description |
---|---|---|---|
0: Clear All | Push (bool) | Unused | Clears the working buffer, optionally pushing it to display at the end |
1: Clear Area | Offset (uint8) |
Area (uint8) |
Clears specified fragment of the working buffer |
2: Push All | Clear (bool) | Unused | Pushes working buffer to the display, optionally clearing it at the end |
3: Push Area | Offset (uint8) |
Area (uint8) |
Pushes specified fragment of the working buffer to the display |
4: Save Default | Clear (bool) | Unused | Saves the working buffer as default overlay, optionally clearing it at the end |
5: Load Default | Push (bool) | Unused | Loads default overlay into the working buffer, optionally pushing it to display at the end |
Offset
encoding:
Bits | Value | Description |
---|---|---|
0:3 | Row | Starting cursor row (0-12) |
4:7 | Column | Starting cursor column (0-15) |
Area
encoding:
Bits | Value | Description |
---|---|---|
0:3 | Height | (Height-1) of modified area in rows |
4:7 | Width | (Width-1) of modified area in columns |
0x94 - Command Display Overlay Update
C Structure format
typedef struct SM_Protocol_DisplayOverlayUpdate_s
{
/** Device ID */
uint8_t did[3];
/** Update offset (starting address) */
struct
{
uint8_t row : 4u; /** Row Id */
uint8_t column : 4u; /** Column Id */
} offset;
/** Map containing symbol IDs to use for addressed overlay blocks */
uint8_t symbolMap[8];
} SM_Protocol_CommandDisplayOverlayUpdate_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 148, length = 12 */
0x94, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
row = 2
column = 3
map = [4, 5, 6, 7, 8, 9, 10, 11]
*/
0x01, 0x02, 0x03, 0x32, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B,
};
Frame transmitted from the PC to the device (Master Anchor) to relay command to target display tags, in order to update content of the overlay working buffer, which contains references to graphic symbols defined inside overlay database.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3 @ bits 0:2 | byte (uint8) | row |
Starting row for working buffer modification |
3 @ bits 3:6 | byte (uint8) | column |
Starting column for working buffer modification |
4-11 | 8 bytes (array uint8) | map |
Map of the symbols (their IDs) to render at consecutive overlay blocks |
0x95 - Command Display Overlay Upload
C Structure format
typedef struct SM_Protocol_DisplayOverlayUpload_s
{
/** Device ID */
uint8_t did[3];
/** Symbol ID */
uint8_t id;
/** Symbol pixel bitmap creating 8x8 graphic */
uint8_t symbolBitmap[8];
} SM_Protocol_CommandDisplayOverlayUpload_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 149, length = 12 */
0x95, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
id = 64
symbolBitmap = [0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70]
*/
0x01, 0x02, 0x03, 0x40, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70, 0x07, 0x70,
};
Frame transmitted from the PC to the device (Master Anchor) to relay command to target display tags, in order to upload symbol bitmap to the overlay graphic database.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3 | byte (uint8) | id |
Symbol ID |
4-11 | 8 bytes (array uint8) | symbolBitmap |
Symbol pixel bitmap creating 8x8 graphic |
Bitmap layout example for EK
string:
Byte/Bit | Bit 0 | Bit 1 | Bit 2 | Bit 3 | Bit 4 | Bit 5 | Bit 6 | Bit 7 | Bitmap byte |
---|---|---|---|---|---|---|---|---|---|
Byte 0 | ⬜ | ⬜ | ⬜ | ⬛ | ⬜ | ⬛ | ⬛ | ⬜ | 0x97 |
Byte 1 | ⬜ | ⬛ | ⬛ | ⬛ | ⬜ | ⬛ | ⬛ | ⬜ | 0x91 |
Byte 2 | ⬜ | ⬛ | ⬛ | ⬛ | ⬜ | ⬛ | ⬜ | ⬛ | 0x51 |
Byte 3 | ⬜ | ⬜ | ⬜ | ⬛ | ⬜ | ⬜ | ⬛ | ⬛ | 0x37 |
Byte 4 | ⬜ | ⬛ | ⬛ | ⬛ | ⬜ | ⬜ | ⬛ | ⬛ | 0x31 |
Byte 5 | ⬜ | ⬛ | ⬛ | ⬛ | ⬜ | ⬛ | ⬜ | ⬛ | 0x51 |
Byte 6 | ⬜ | ⬛ | ⬛ | ⬛ | ⬜ | ⬛ | ⬛ | ⬜ | 0x91 |
Byte 7 | ⬜ | ⬜ | ⬜ | ⬛ | ⬜ | ⬛ | ⬛ | ⬜ | 0x97 |
0x96 - Command MOx setup
C Structure format
typedef struct SM_Protocol_CommandMoxSetup_s
{
/** Device ID */
uint8_t did[3];
/** PWM value */
uint8_t pwm;
/** Unused command padding */
uint8_t padding[8];
} SM_Protocol_CommandMoxSetup_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 150, length = 12 */
0x96, 0x0c, 0x00,
/* Value buffer */
/* Device 0:
did = [1, 2, 3],
pwm = 50,
padding = [0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00],
*/
0x01, 0x02, 0x03, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to relay command to target display tags, in order to update MOx measurement setup. Currently, one parameter is configurable - PWM duty cycle of the light source.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3 | byte (uint8) | pwm |
Duty cycle of light source PWM |
4-11 | 8 bytes (array uint8) | padding |
Command padding, unused |
0xB4 - Command Set ESP Config 1
C Structure format
typedef struct SM_Protocol_EspControl_Message_Network1_s
{
SM_Protocol_DID_t did;
Esp_Settings_Esp_Config_t config;
uint8_t ipAddress[4];
uint8_t networkMask[4];
} SM_Protocol_EspControl_Message_Network1_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 180, length = 12 */
0xb4, 0x0c, 0x00,
/* Value buffer
did = [1, 2, 3],
config = [3],
ipAddress = [192, 168, 1, 10],
networkMask = [255, 255, 255, 0],
*/
0x01, 0x02, 0x03, 0x03, 0xc0, 0xa8, 0x01, 0x0a,
0xff, 0xff, 0xff, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to change configuration of ESP32.
This frame consists four parameters: target DID, config bits and IP address and Network mask for Ethernet when static IP mode is used.
Config is a bitfield consisting of following value bits:
- Bit 0 - ESP enabled - if true, ESP is powered on. If false, ESP is disabled
- Bit 1 - DHCP enabled - if true, ESP will obtain Ethernet configuration parameters via DHCP. If false, static configuration will be used.
- Bit 2 - WiFi AP enabled - if true, ESP WiFi interface is configured in Access Point mode. If false, WiFi is disabled.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3 | byte (uint8) | config |
ESP32 config bits |
4-7 | 4 bytes (array uint8) | ipAddress |
ETH IP address |
8-11 | 4 bytes (array uint8) | networkMask |
ETH Network mask |
0xB5 - Command Set ESP Config 2
C Structure format
typedef struct SM_Protocol_EspControl_Message_Network2_s
{
SM_Protocol_DID_t did;
uint8_t defaultGateway[4];
/* Padding - currently unused */
uint8_t padding[5];
} SM_Protocol_EspControl_Message_Network2_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 181, length = 12 */
0xb5, 0x0c, 0x00,
/* Value buffer
did = [1, 2, 3],
defaultGateway = [192, 168, 1, 1],
padding = [0, 0, 0, 0, 0],
*/
0x01, 0x02, 0x03, 0xc0, 0xa8, 0x01, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to change configuration of ESP32. This frame consists two parameters: target DID and IP address of default gateway for Ethernet when static IP mode is used.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-6 | 4 bytes (array uint8) | defaultGateway |
Default Gateway IP address |
7-11 | 5 bytes (array uint8) | padding |
Command padding, unused |
0xB6 - Command Set ESP WiFi password 1
C Structure format
typedef struct SM_Protocol_EspControl_Message_WifiPassword_s
{
SM_Protocol_DID_t did;
uint8_t password[9];
} SM_Protocol_EspControl_Message_WifiPassword_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 182, length = 12 */
0xb6, 0x0c, 0x00,
/* Value buffer
did = [1, 2, 3],
password = [112, 97, 115, 115, 119, 111, 114, 100, 49]
*/
0x01, 0x02, 0x03, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x31,
};
Frame transmitted from the PC to the device (Master Anchor) to change first nine characters of WiFi password. Maximum allowed password length is limited to 18 (including null terminator), so it is divided in two frames - 0xB6 and 0xB7. Command 0xB6 clears currently saved password and writes nine first characters. Then, if password is longer than 9 characters, second frame (0xB7) must be sent. This frame consists two parameters: target DID and password string.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-11 | 9 bytes (array uint8) | password |
First 9 characters of password |
0xB7 - Command Set ESP WiFi password 2
C Structure format
typedef struct SM_Protocol_EspControl_Message_WifiPassword_s
{
SM_Protocol_DID_t did;
uint8_t password[9];
} SM_Protocol_EspControl_Message_WifiPassword_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 183, length = 12 */
0xb7, 0x0c, 0x00,
/* Value buffer
did = [1, 2, 3],
password = [112, 97, 115, 115, 119, 111, 114, 100, 49]
*/
0x01, 0x02, 0x03, 0x70, 0x61, 0x73, 0x73,
0x77, 0x6f, 0x72, 0x64, 0x31,
};
Frame transmitted from the PC to the device (Master Anchor) to change last nine characters of WiFi password. Maximum allowed password length is limited to 18 (including null terminator), so it is divided in two frames - 0xB6 and 0xB7. Command 0xB7 reads currently saved password and changes its nine last characters. This frame consists two parameters: target DID and password string.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-11 | 9 bytes (array uint8) | password |
Last 9 characters of password |
0xC4 - Command Commit Seat Plan
C Structure format
typedef struct SM_Protocol_CommandCommitSeatPlan_s
{
SM_Protocol_DID_t did;
uint8_t version;
uint8_t checksum;
uint8_t padding[7]; // Command padding - unused
} SM_Protocol_CommandCommitSeatPlan_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 183, length = 12 */
0xc4, 0x0c, 0x00,
/* Value buffer
did = [1, 2, 3],
version = 123,
checksum = 165,
padding = [0, 0, 0, 0, 0, 0, 0]
*/
0x01, 0x02, 0x03, 0x7b, 0xa5, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to indicate that dynamic seat plan is ready to be used.
This frame consists three parameters: target DID, seat plan version and its checksum.
The checksum is calculated as a CRC-CCITT-8 sum with initial valiue 0xFF of all frequencies present in the plan.
When seat plan was changed and the checksum is correct, calling this command will result in a device reset.
On power-up, transferred seat plan will be verified for correctness and, if it is correct, will be used instead of a default one.
If there was no change to the seat plan, the reset will be ignored. If provided checksum is not equal to the checksum calculated
from the seat plan on the device, no action is performed.
Checksum verification can be disabled by setting checksum value to 0xFF. However, value of 0xFF is also a valid
checksum that can occur for certain input data. To avoid this problem, when checksum calculated in the firmware
is equal to 0xFF, result is modified by appending frequency value of the 0. slot to the end of the frequency array.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3 | byte (uint8) | version |
Seat plan version number |
4 | byte (uint8) | checksum |
Seat plan checksum |
5-11 | 3 bytes (array uint8) | padding |
Command padding - unused |
0xC5 - Command Set Seat Plan
C Structure format
typedef struct SM_Protocol_CommandSetSeatPlan_s
{
SM_Protocol_DID_t did;
struct
{
uint8_t id;
uint8_t frequency;
} seatConfig[4];
uint8_t padding; // Command padding - unused
} SM_Protocol_CommandSetSeatPlan_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 197, length = 12 */
0xc5, 0x0c, 0x00,
/* Value buffer
did = [1, 2, 3]
Seat config 0:
id = 1
freq = 5
Seat config 1:
id = 5
freq = 9
Seat config 2:
id = 3
freq = 4
Seat config 3:
id = 20
freq = 4
padding = 0
*/
0x01, 0x02, 0x03, 0x01, 0x05, 0x05, 0x09,
0x03, 0x04, 0x14, 0x04, 0x00,
};
Frame transmitted from the PC to the device (Master Anchor) to set up to four new seat configs. The frame consists of target DID and four seat configs (position in the seat plan (id) and frequency). If frequency is equal to 0, the entry is omitted.
Byte | Storage | Field | Description |
---|---|---|---|
0-2 | 3 bytes (array uint8) | did |
Three bytes long Node ID |
3-10 | 8 bytes | seat config |
Array of four seat config entries |
11 | byte (uint8) | padding |
Command padding - unused |
The seat plan defines order of tags with different frequencies in the cycle.
Each seat in the seat plan is parametrized with its supported frequency.
When tag with supported frequency joins the network, the network admninistrator will assign
it a seat with this frequency, if free seat is available.
Currently used seat plan consists of 41 seats and covers half of the cycle.
Second half of the cycle is the same as the first one.
Tags with frequency 25 Hz use slots only in one half of the cycle, the second is unused.
High frequency tags (75 Hz and higher) will occupy more than one seat. There is a defined
seat separation between seats of a high frequency tag. The number of occurrences and distance
between them depends on the frequency:
Frequency | Separation |
---|---|
75 Hz | 34 |
100Hz | 16, 18 |
125Hz | 8, 17, 9 |
150 Hz | 8, 8, 9, 9 |
175Hz | 8, 8, 8, 8, 8 |
For example, if slot number 1 is defined as 75 Hz, slot number 35 also will be set to 75 Hz. If user sets slot number 3 to 125 Hz, also slots 11, 28 and 37 will be set to 125 Hz. Updating slot separation is done automatically in the firmware, so only primary setting must be provided, but user have to remember that settings for separated slots will be overwritten. Also, trying to set high frequency seat in a way that the next separated slots will not fit into the seat plan array will be rejected.
Frequency is an uint8 value that is mapped as follows:
Frequency ID | Frequency |
---|---|
0 | Unknown |
1 | Random |
2 | Very Slow |
3 | Slow |
4 | 25 Hz |
5 | 50 Hz |
6 | 75 Hz |
7 | 100 Hz |
8 | 125 Hz |
9 | 150 Hz |
10 | 175 Hz |
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 |
0xC7 - Command Blink Pylon
C Structure format
typedef struct SM_Protocol_CommandBlinkPylon_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_CommandBlinkPylon_t;
Frame example
uint8_t rawData[] =
{
/* TLV header: type = 199, length = 12 */
0xc7, 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;
*/
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. Unlike all other commands, this one is routed "blindly", without checking if the recipent device was active in the current cycle. This behavior is required in case of Pylon tags that are registered in the network as slow tags and therefore are not active in every cycle, but they should be able to execute blink request immediately.
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] |
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;
*/
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
[1.2.1] - 2024-12-23
Added
- Added Seat Plan Version field to Admin Distribution data
[1.2.0] - 2024-11-22
Added
- Added definition for Seat Plan modification commands (0xC4 and 0xC5)
[1.1.0] - 2024-07-12
Added
- Added description for the new Blink Pylon command.
[1.0.1] - 2024-06-21
Added
- Added description for the new MOx setup command.
Changed
- Updated description of MOx data in Admin Distribution frame
[1.0.0] - 2024-05-20
Changed
- Updated and extended device type description.
[0.16.0] - 2024-05-10
Added
- Added description for the new board config bit (3) controlling WOM behavior during charging.
- Added description for the new board config bit (4) controlling haptic operation.
- Added
Impact
frame description. - Added ESP32 WiFi config description
Changed
- Extended overlay row addressing range to 4 bits.
- Extended BLE Tx power presets range.
- Changed Admin Distribution Info TLV message structure to include platform specific sensor data.
[0.15.0] - 2024-04-17
Added
- Added anchor seat pool field to the
Set Network Configuration
command. - Display Overlay Command command definition.
- Display Overlay Update command definition.
- Display Overlay Upload command definition.
- ESP32 configuration commands.
[0.14.0] - 2024-03-27
Added
- Set Magnetometer Calibration command definition.
- Set BLE config command definition.
- Set Heart Rate MAC address command definition.
- Information about broadcast addressing.
Changed
- Changed Admin Distribution Info TLV message structure to sync with latest firmware changes.
- Updated IMU calibration command definition.
[0.13.0] - 2024-03-20
Added
- Update License command definition.
Changed
- Changed Admin Distribution Info TLV message structure to include required licensing data.
[0.12.0] - 2024-02-19
Added
- Set Name command definition.
- Set Group command definition.
- Set Serial command definition.
- Set IMU Calibration command definition.
- Set Message command definition.
[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: