Frame Reference
Every frame the unit emits decodes into a typed struct inside the
oscp_frame_t union. Branch on frame.type, then read the matching member via
its accessor macro.
frame.type |
Value | Struct | Accessor | Decoded size |
|---|---|---|---|---|
OSCP_FRAME_RAW |
0x00 |
oscp_raw_t |
oscp_raw(&f) |
61 B |
OSCP_FRAME_EULER |
0x01 |
oscp_euler_t |
oscp_euler(&f) |
25 B |
OSCP_FRAME_QUATERNION |
0x02 |
oscp_quat_t |
oscp_quat(&f) |
29 B |
OSCP_FRAME_ROT_MATRIX |
0x03 |
oscp_rot_mat_t |
oscp_rot_mat(&f) |
49 B |
OSCP_FRAME_GNSS |
0x04 |
oscp_gnss_t |
oscp_gnss(&f) |
64 B |
OSCP_FRAME_DEBUG_1 |
0x05 |
oscp_debug_1_t |
oscp_debug_1(&f) |
58 B |
OSCP_FRAME_DEBUG_2 |
0x06 |
oscp_debug_2_t |
oscp_debug_2(&f) |
58 B |
OSCP_FRAME_STARTUP |
0x07 |
oscp_startup_t |
oscp_startup(&f) |
40 B |
Info
Command responses from the IMU surface as additional frame.type values
with no payload: OSCP_FRAME_CMD_SUCCESS (0xA0), OSCP_FRAME_CMD_FAILED
(0xA1), OSCP_FRAME_CMD_UNKNOWN (0xA2) and OSCP_FRAME_CMD_NOT_IMPL
(0xA3). These are purely added by the C Library and are not native frame types from the IMU.
The header byte
Every operating frame begins with a packed header byte. Decode it with the supplied macros rather than by hand:
oscp_frame_type_t t = OSCP_HDR_FRAME_TYPE(f); /* bits [2:0] */
oscp_operating_mode_t om = OSCP_HDR_OPERATING_MODE(f); /* bits [5:3] */
oscp_misalignment_corr_t mc = OSCP_HDR_MISALIGNMENT_CORR(f); /* bits [7:6] */
| Field | Bits | Values |
|---|---|---|
| Frame type | [2:0] |
see table above |
| Operating mode | [5:3] |
OSCP_OP_MODE_IDLE / _LOW / _MEDIUM |
| Misalignment correction | [7:6] |
OSCP_MISALIGNMENT_CORR_DISABLED / _ENABLED |
The status byte
Every frame carries a status byte. 0x00 means all clear; otherwise mask
against the flags below.
| Mask | Value | Meaning |
|---|---|---|
OSCP_STATUS_OK |
0x00 |
No bits set - healthy |
OSCP_STATUS_OVERRUN |
0x01 |
IMU real-time controller overrun |
OSCP_STATUS_MEMS_ERR |
0x02 |
MEMS sensor error |
OSCP_STATUS_INCL_ERR |
0x04 |
Inclinometer error |
OSCP_STATUS_MAG_ERR |
0x08 |
Magnetometer error |
OSCP_STATUS_TEMP_ERR |
0x10 |
Temperature sensor error |
OSCP_STATUS_GNSS_ERR |
0x20 |
GNSS error (G variants only) |
OSCP_STATUS_OG_ERR |
0x40 |
Optical gyroscope error (optical-based models only) |
if (e->status & OSCP_STATUS_MEMS_ERR) { /* handle MEMS fault */ }
Raw frame - oscp_raw_t
Full raw sensor output.
Fields
| Field | Type | Unit |
|---|---|---|
header_byte |
uint8_t |
- |
counter |
uint8_t |
- |
timestamp_ms |
uint64_t |
ms |
gyro_x/y/z |
float |
dps |
accel_x/y/z |
float |
g |
incl_x/y |
float |
mg |
mag_x/y/z |
float |
µT |
temp |
float |
°C |
status |
uint8_t |
- |
crc |
uint16_t |
- |
Euler frame - oscp_euler_t
AHRS attitude as Euler angles.
Fields
| Field | Type | Unit |
|---|---|---|
header_byte |
uint8_t |
- |
counter |
uint8_t |
- |
timestamp_ms |
uint64_t |
ms |
roll |
float |
deg |
pitch |
float |
deg |
yaw |
float |
deg |
status |
uint8_t |
- |
crc |
uint16_t |
- |
Quaternion frame - oscp_quat_t
AHRS attitude as a unit quaternion (w, x, y, z).
Fields
| Field | Type | Unit |
|---|---|---|
header_byte |
uint8_t |
- |
counter |
uint8_t |
- |
timestamp_ms |
uint64_t |
ms |
w, x, y, z |
float |
- (normalized) |
status |
uint8_t |
- |
crc |
uint16_t |
- |
Rotation matrix frame - oscp_rot_mat_t
AHRS attitude as a 3×3 direction-cosine matrix.
Fields
| Field | Type | Notes |
|---|---|---|
header_byte |
uint8_t |
- |
counter |
uint8_t |
- |
timestamp_ms |
uint64_t |
ms |
rm[3][3] |
float |
row-major direction-cosine matrix |
status |
uint8_t |
- |
crc |
uint16_t |
- |
GNSS frame - oscp_gnss_t
Position, velocity and fix quality.
Fields
| Field | Type | Unit |
|---|---|---|
header_byte |
uint8_t |
- |
counter |
uint8_t |
- |
timestamp_ms |
uint64_t |
ms |
gnss_fix_type |
uint8_t |
- |
num_satellites |
uint8_t |
count |
longitude |
float |
deg |
latitude |
float |
deg |
height |
int32_t |
mm |
horizontal_accuracy |
uint32_t |
mm |
vertical_accuracy |
uint32_t |
mm |
velocity_north/east/down |
int32_t |
mm/s |
speed_accuracy |
uint32_t |
mm/s |
heading_of_motion |
float |
deg |
heading_accuracy |
float |
deg |
pdop |
float |
- |
gnssFixOk : 1 |
bitfield |
fix valid |
invalidLLH : 1 |
bitfield |
lat/lon/height invalid |
reserved : 2 |
bitfield |
- |
lastCorrectionAge : 4 |
bitfield |
- |
status |
uint8_t |
- |
crc |
uint16_t |
- |
Debug frames - oscp_debug_1_t / oscp_debug_2_t
User / diagnostic frames. Debug 1 carries per-axis sensor bias user registers and
user filter settings; Debug 2 carries the user magnetometer calibration matrix and AHRS
fusion parameters. Both are opaque uint32_t register dumps - see the datasheet
for interpretation. Request them with the OFD operating frame command
(oscp_cmd_of(..., OSCP_FRAME_SEL_DEBUG, ...)) while in CONFIG state.
Startup frame - oscp_startup_t
Emitted once at boot or when requested with the SUF command (oscp_cmd_suf(...)) while in CONFIG state.. Identifies the unit and reports its saved configuration.
Fields
| Field | Type | Notes |
|---|---|---|
header_byte |
uint8_t |
- |
mark_number[10] |
char |
not null-terminated - see warning below |
unit_number |
uint16_t |
unit number |
sw_major_ver / sw_minor_ver / sw_patch_ver |
uint8_t |
firmware version |
enabled_frames |
uint8_t |
bitmask, see below |
gyro_dr / accel_dr / incl_dr |
bitfield |
dynamic ranges |
gyro_* / accel_* filters |
bitfield |
filter config |
ahrs_convention / ahrs_heading_src |
bitfield |
AHRS config |
ahrs_gain / ahrs_accel_rej / ahrs_mag_rej |
float |
AHRS config |
ahrs_rec_trig_per |
uint32_t |
AHRS config |
status |
uint8_t |
- |
crc |
uint16_t |
- |
The enabled_frames bitmask uses these flags:
| Mask | Value |
|---|---|
OSCP_ENABLE_RAW |
0x01 |
OSCP_ENABLE_EULER |
0x02 |
OSCP_ENABLE_QUAT |
0x04 |
OSCP_ENABLE_ROT_MAT |
0x08 |
OSCP_ENABLE_GNSS |
0x10 |
mark_number is not null-terminated
mark_number is a fixed 10-byte field with no terminator. Do not pass it
straight to printf("%s"). Copy it into an 11-byte buffer and terminate it
yourself:
char mark[11];
memcpy(mark, s->mark_number, sizeof(s->mark_number));
mark[10] = '\0';
Packed structs - do not take a bare float *
Frame structs mirror the wire format and are packed. Reading a field
through the struct (e->roll) is safe, but taking a float * into a
member and dereferencing it can fault on strict-alignment cores (an
unaligned VLDR on Cortex-M7). Copy into aligned locals before doing float
math:
const float gx = r->gyro_x, gy = r->gyro_y, gz = r->gyro_z;
Next: Command reference →