Skip to content

Commit

Permalink
Fixed-point/double types supported by MData2 callback event handler
Browse files Browse the repository at this point in the history
Implementation for #10
  • Loading branch information
Scottapotamas committed Oct 9, 2022
1 parent 534e5dc commit 21350e9
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 13 deletions.
46 changes: 42 additions & 4 deletions src/xsens_mdata2.c
Original file line number Diff line number Diff line change
Expand Up @@ -138,10 +138,25 @@ void xsens_mdata2_decode_field( mdata2_packet_t *output, callback_event_t evt_cb
// Apply post-processing (BE->LE) strategy specific to the packet type
if( decode_rule )
{
// The structure describes the union type
// - for situations where non-single precision is used, apply an offset to the enum
// to correctly describe the type as fixed-precision or double, etc
value.type = decode_rule->type + ( number_precision * 10 );
// The structure describes the typical type
value.type = decode_rule->type;

// For situations where non-single precision is used, apply an offset to the enum
// to correctly describe the type as fixed-precision or double, etc
if( number_precision )
{
if( decode_rule->type < XSENS_EVT_TYPE_FLOAT )
{
// Enum offset doesn't apply cleanly for non-float default values
// So we 'zero' out the table's value, and use the precision offset to get
// the single-value type field of that type
value.type = XSENS_EVT_TYPE_FLOAT + ( number_precision * 10 );
}
else
{
value.type = decode_rule->type + ( number_precision * 10 );
}
}

// Convert BE data to LE, put it in the right union field
switch( value.type )
Expand Down Expand Up @@ -197,6 +212,29 @@ void xsens_mdata2_decode_field( mdata2_packet_t *output, callback_event_t evt_cb
value.data.f4x9[8] = xsens_coalesce_32BE_F32LE( &output->payload[32] );
break;

case XSENS_EVT_TYPE_1632FP:
xsens_swap_endian_u48( &value.data.fp1632, &output->payload[0] );
break;

case XSENS_EVT_TYPE_1632FP2:

break;

case XSENS_EVT_TYPE_1632FP3:

break;

case XSENS_EVT_TYPE_1632FP4:
xsens_swap_endian_u48( &value.data.fp1632x4[0], &output->payload[0] );
xsens_swap_endian_u48( &value.data.fp1632x4[1], &output->payload[6] );
xsens_swap_endian_u48( &value.data.fp1632x4[2], &output->payload[12] );
xsens_swap_endian_u48( &value.data.fp1632x4[3], &output->payload[18] );
break;

case XSENS_EVT_TYPE_1632FP9:

break;

case XSENS_EVT_TYPE_DOUBLE:
xsens_swap_endian_u64( &value.data.f8, &output->payload[0] );
break;
Expand Down
15 changes: 13 additions & 2 deletions src/xsens_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,17 @@ void xsens_swap_endian_u32( uint8_t *dest, uint8_t *source )
dest[0] = source[3];
}

// As per manual, big-endian 32-bit first, then BE 16-bit part i.e [b3, b2, b1, b0, b5, b4]
void xsens_swap_endian_u48( uint8_t *dest, uint8_t *source )
{
dest[0] = source[3];
dest[1] = source[2];
dest[2] = source[1];
dest[3] = source[0];
dest[4] = source[5];
dest[5] = source[4];
}

void xsens_swap_endian_u64( uint8_t *dest, uint8_t *source )
{
dest[7] = source[0];
Expand Down Expand Up @@ -114,10 +125,10 @@ float xsens_fp1220_to_f32( int32_t value )

int64_t xsens_f64_to_fp1632( double value )
{
return value * (2ULL<<32-1);
return (uint64_t)(value * (2ULL<<32-1))&0x0000FFFFFFFFFFFF;
}

double xsens_fp1632_to_f64( int64_t value )
{
return (double)value / (2ULL<<32-1);
return (double)(value&0x0000FFFFFFFFFFFF) / (2ULL<<32-1);
}
30 changes: 24 additions & 6 deletions test/test_xsens_mti_parse_messages.c
Original file line number Diff line number Diff line change
Expand Up @@ -499,12 +499,23 @@ void test_parse_mdata2_number_formats( void )
result_pry[2] = xsens_fp1220_to_f32( cb_evt_data_cache[1].data.fp1220x3[2] );
TEST_ASSERT_EQUAL_FLOAT_ARRAY( golden_pry, result_pry, 3);


// DeltaQ
TEST_ASSERT_EQUAL_INT( XSENS_EVT_DELTA_Q, cb_evt_flag_cache[7] );
TEST_ASSERT_EQUAL_INT( XSENS_EVT_TYPE_FLOAT4, cb_evt_data_cache[7].type );
float golden_dq[4] = { 1.000000000233, -0.000429107808, -0.000302935718, -0.000177090988 };
TEST_ASSERT_EQUAL_FLOAT_ARRAY( golden_dq, cb_evt_data_cache[1].data.f4x4, 4);
TEST_ASSERT_EQUAL_INT( XSENS_EVT_DELTA_Q, cb_evt_flag_cache[2] );
TEST_ASSERT_EQUAL_INT( XSENS_EVT_TYPE_1632FP4, cb_evt_data_cache[2].type );
double golden_dq[4] = { 1.000000000233, -0.000429107808, -0.000302935718, -0.000177090988 };

// Convert the fixed-point 1632 delta-quaternion array[4] into doubles
double result_dq[4] = { 0 };
result_dq[0] = xsens_fp1632_to_f64( cb_evt_data_cache[2].data.fp1632x4[0] );
result_dq[1] = xsens_fp1632_to_f64( cb_evt_data_cache[2].data.fp1632x4[1] );
result_dq[2] = xsens_fp1632_to_f64( cb_evt_data_cache[2].data.fp1632x4[2] );
result_dq[3] = xsens_fp1632_to_f64( cb_evt_data_cache[2].data.fp1632x4[3] );

double flt_epsilon = 0.00000000000050000;
TEST_ASSERT_DOUBLE_WITHIN( flt_epsilon, golden_dq[0], result_dq[0] );
TEST_ASSERT_DOUBLE_WITHIN( flt_epsilon, golden_dq[1], result_dq[1] );
TEST_ASSERT_DOUBLE_WITHIN( flt_epsilon, golden_dq[2], result_dq[2] );
TEST_ASSERT_DOUBLE_WITHIN( flt_epsilon, golden_dq[3], result_dq[3] );

// MagneticField
TEST_ASSERT_EQUAL_INT( XSENS_EVT_MAGNETIC, cb_evt_flag_cache[3] );
Expand All @@ -529,6 +540,8 @@ void test_parse_mdata2_number_formats_2( void )
// (magX: 0.9619465, magY: -0.2602215, magZ: 1.7812529)),
// (Temperature|Fp1632, 6 bytes, Temp: 24.375000000000),
// (Pressure|Double, 8 bytes, Pressure: 101669),
// MT Manager configuration, packet viewer and MID show this as double, but actual packet is 4-byte uint32
// TODO: report MTManager/documentation/firmware bug to xsens?

uint8_t test_packet[] = { 0xFA,
0xFF,
Expand Down Expand Up @@ -570,7 +583,12 @@ void test_parse_mdata2_number_formats_2( void )

// Pressure
TEST_ASSERT_EQUAL_INT( XSENS_EVT_PRESSURE, cb_evt_flag_cache[4] );

// Probable bug in firmware/MTManager output - configuration asked for double precision and the
// identifier reflects that
TEST_ASSERT_EQUAL_INT( XSENS_EVT_TYPE_DOUBLE, cb_evt_data_cache[4].type );
TEST_ASSERT_EQUAL_DOUBLE( 101669, cb_evt_data_cache[4].data.f8);
// but the actual payload is still a uint32, so this test fails

// TEST_ASSERT_EQUAL_INT( 101669, cb_evt_data_cache[4].data.u4);

}
2 changes: 1 addition & 1 deletion test/test_xsens_utility.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,7 +224,7 @@ void test_into_fp1632( void )
void test_into_fp1632_negative( void )
{
// Value is one-bit higher than 0x24395810 example
int64_t expected = 0xFFFFFFFCDBC6A7F0; // Negative/signed equiv from 0x00032439580F
int64_t expected = 0xFFFCDBC6A7F0; // Negative/signed equiv from 0x00032439580F

double value = -3.1415;
int64_t result = xsens_f64_to_fp1632( value );
Expand Down

0 comments on commit 21350e9

Please sign in to comment.