@ -48,6 +48,10 @@ ICM20689::ICM20689(I2CSPIBusOption bus_option, int bus, uint32_t device, enum Ro
@@ -48,6 +48,10 @@ ICM20689::ICM20689(I2CSPIBusOption bus_option, int bus, uint32_t device, enum Ro
_px4_accel ( get_device_id ( ) , ORB_PRIO_HIGH , rotation ) ,
_px4_gyro ( get_device_id ( ) , ORB_PRIO_HIGH , rotation )
{
if ( drdy_gpio ! = 0 ) {
_drdy_interval_perf = perf_alloc ( PC_INTERVAL , MODULE_NAME " : DRDY interval " ) ;
}
ConfigureSampleRate ( _px4_gyro . get_max_rate_hz ( ) ) ;
}
@ -77,6 +81,7 @@ int ICM20689::init()
@@ -77,6 +81,7 @@ int ICM20689::init()
bool ICM20689 : : Reset ( )
{
_state = STATE : : RESET ;
DataReadyInterruptDisable ( ) ;
ScheduleClear ( ) ;
ScheduleNow ( ) ;
return true ;
@ -91,8 +96,8 @@ void ICM20689::exit_and_cleanup()
@@ -91,8 +96,8 @@ void ICM20689::exit_and_cleanup()
void ICM20689 : : print_status ( )
{
I2CSPIDriverBase : : print_status ( ) ;
PX4_INFO ( " FIFO empty interval: %d us (%.3f Hz) " , _fifo_empty_interval_us ,
static_cast < double > ( 1000000 / _fifo_empty_interval_us ) ) ;
PX4_INFO ( " FIFO empty interval: %d us (%.3f Hz) " , _fifo_empty_interval_us , 1e6 / _fifo_empty_interval_us ) ;
perf_print_counter ( _transfer_perf ) ;
perf_print_counter ( _bad_register_perf ) ;
@ -120,13 +125,17 @@ int ICM20689::probe()
@@ -120,13 +125,17 @@ int ICM20689::probe()
void ICM20689 : : RunImpl ( )
{
const hrt_abstime now = hrt_absolute_time ( ) ;
switch ( _state ) {
case STATE : : RESET :
// PWR_MGMT_1: Device Reset
RegisterWrite ( Register : : PWR_MGMT_1 , PWR_MGMT_1_BIT : : DEVICE_RESET ) ;
_reset_timestamp = hrt_absolute_time ( ) ;
_reset_timestamp = now ;
_consecutive_failures = 0 ;
_total_failures = 0 ;
_state = STATE : : WAIT_FOR_RESET ;
ScheduleDelayed ( 1 _ms ) ;
ScheduleDelayed ( 100 _ms ) ;
break ;
case STATE : : WAIT_FOR_RESET :
@ -136,13 +145,18 @@ void ICM20689::RunImpl()
@@ -136,13 +145,18 @@ void ICM20689::RunImpl()
if ( ( RegisterRead ( Register : : WHO_AM_I ) = = WHOAMI )
& & ( RegisterRead ( Register : : PWR_MGMT_1 ) = = 0x40 ) ) {
// Wakeup and reset digital signal path
RegisterWrite ( Register : : PWR_MGMT_1 , 0 ) ;
RegisterWrite ( Register : : SIGNAL_PATH_RESET , SIGNAL_PATH_RESET_BIT : : ACCEL_RST | SIGNAL_PATH_RESET_BIT : : TEMP_RST ) ;
RegisterSetAndClearBits ( Register : : USER_CTRL , USER_CTRL_BIT : : SIG_COND_RST , USER_CTRL_BIT : : I2C_IF_DIS ) ;
// if reset succeeded then configure
_state = STATE : : CONFIGURE ;
ScheduleNow ( ) ;
ScheduleDelayed ( 35 _ms ) ; // max 35 ms start-up time from sleep
} else {
// RESET not complete
if ( hrt_elapsed_time ( & _reset_timestamp ) > 100 _ms ) {
if ( hrt_elapsed_time ( & _reset_timestamp ) > 1000 _ms ) {
PX4_DEBUG ( " Reset failed, retrying " ) ;
_state = STATE : : RESET ;
ScheduleDelayed ( 100 _ms ) ;
@ -164,7 +178,7 @@ void ICM20689::RunImpl()
@@ -164,7 +178,7 @@ void ICM20689::RunImpl()
_data_ready_interrupt_enabled = true ;
// backup schedule as a watchdog timeout
ScheduleDelayed ( 10 _ms ) ;
ScheduleDelayed ( 100 _ms ) ;
} else {
_data_ready_interrupt_enabled = false ;
@ -174,82 +188,88 @@ void ICM20689::RunImpl()
@@ -174,82 +188,88 @@ void ICM20689::RunImpl()
FIFOReset ( ) ;
} else {
PX4_DEBUG ( " Configure failed, retrying " ) ;
// try again in 10 ms
// CONFIGURE not complete
if ( hrt_elapsed_time ( & _reset_timestamp ) > 1000 _ms ) {
PX4_DEBUG ( " Configure failed, resetting " ) ;
_state = STATE : : RESET ;
} else {
PX4_DEBUG ( " Configure failed, retrying " ) ;
}
ScheduleDelayed ( 10 _ms ) ;
}
break ;
case STATE : : FIFO_READ : {
hrt_abstime timestamp_sample = 0 ;
uint8_t samples = 0 ;
if ( _data_ready_interrupt_enabled ) {
// re-schedule as watchdog timeout
ScheduleDelayed ( 10 _ms ) ;
// timestamp set in data ready interrupt
if ( ! _force_fifo_count_check ) {
samples = _fifo_read_samples . load ( ) ;
} else {
const uint16_t fifo_count = FIFOReadCount ( ) ;
samples = ( fifo_count / sizeof ( FIFO : : DATA ) / SAMPLES_PER_TRANSFER ) * SAMPLES_PER_TRANSFER ; // round down to nearest
// scheduled from interrupt if _drdy_fifo_read_samples was set
if ( _drdy_fifo_read_samples . fetch_and ( 0 ) = = _fifo_gyro_samples ) {
perf_count_interval ( _drdy_interval_perf , now ) ;
}
timestamp_sample = _fifo_watermark_interrupt_timestamp ;
// push backup schedule back
ScheduleDelayed ( _fifo_empty_interval_us * 2 ) ;
}
bool failure = false ;
// always check current FIFO count
bool success = false ;
const uint16_t fifo_count = FIFOReadCount ( ) ;
if ( fifo_count > = FIFO : : SIZE ) {
FIFOReset ( ) ;
perf_count ( _fifo_overflow_perf ) ;
// manually check FIFO count if no samples from DRDY or timestamp looks bogus
if ( ! _data_ready_interrupt_enabled | | ( samples = = 0 )
| | ( hrt_elapsed_time ( & timestamp_sample ) > ( _fifo_empty_interval_us / 2 ) ) ) {
} else if ( fifo_count = = 0 ) {
perf_count ( _fifo_empty_perf ) ;
// use the time now roughly corresponding with the last sample we'll pull from the FIFO
timestamp_sample = hrt_absolute_time ( ) ;
const uint16_t fifo_count = FIFOReadCount ( ) ;
samples = ( fifo_count / sizeof ( FIFO : : DATA ) / SAMPLES_PER_TRANSFER ) * SAMPLES_PER_TRANSFER ; // round down to nearest
} else {
// FIFO count (size in bytes) should be a multiple of the FIFO::DATA structure
const uint8_t samples = ( fifo_count / sizeof ( FIFO : : DATA ) / SAMPLES_PER_TRANSFER ) *
SAMPLES_PER_TRANSFER ; // round down to nearest
if ( samples > FIFO_MAX_SAMPLES ) {
// not technically an overflow, but more samples than we expected or can publish
FIFOReset ( ) ;
perf_count ( _fifo_overflow_perf ) ;
} else if ( samples > = 1 ) {
if ( FIFORead ( now , samples ) ) {
success = true ;
_consecutive_failures = 0 ;
}
}
}
if ( samples > FIFO_MAX_SAMPLES ) {
// not technically an overflow, but more samples than we expected or can publish
perf_count ( _fifo_overflow_perf ) ;
failure = true ;
FIFOReset ( ) ;
if ( ! success ) {
_consecutive_failures + + ;
_total_failures + + ;
} else if ( samples > = SAMPLES_PER_TRANSFER ) {
// require at least SAMPLES_PER_TRANSFER (we want at least 1 new accel sample per transfer)
if ( ! FIFORead ( timestamp_sample , samples ) ) {
failure = true ;
_px4_accel . increase_error_count ( ) ;
_px4_gyro . increase_error_count ( ) ;
// full reset if things are failing consistently
if ( _consecutive_failures > 100 | | _total_failures > 1000 ) {
Reset ( ) ;
return ;
}
} else if ( samples = = 0 ) {
failure = true ;
perf_count ( _fifo_empty_perf ) ;
}
if ( failure | | hrt_elapsed_time ( & _last_config_check_timestamp ) > 10 _ms ) {
// check registers incrementally
if ( RegisterCheck ( _register_cfg [ _checked_register ] , true ) ) {
_last_config_check_timestamp = timestamp_sample ;
if ( ! success | | hrt_elapsed_time ( & _last_config_check_timestamp ) > 10 _ms ) {
// check configuration registers periodically or immediately following any failure
if ( RegisterCheck ( _register_cfg [ _checked_register ] ) ) {
_last_config_check_timestamp = now ;
_checked_register = ( _checked_register + 1 ) % size_register_cfg ;
} else {
// register check failed, force reconfigure
PX4_DEBUG ( " Health check failed, reconfiguring " ) ;
_state = STATE : : CONFIGURE ;
ScheduleNow ( ) ;
// register check failed, force reset
perf_count ( _bad_register_perf ) ;
Reset ( ) ;
}
} else {
// periodically update temperature (1 Hz)
if ( hrt_elapsed_time ( & _temperature_update_timestamp ) > 1 _s ) {
// periodically update temperature (~ 1 Hz)
if ( hrt_elapsed_time ( & _temperature_update_timestamp ) > = 1 _s ) {
UpdateTemperature ( ) ;
_temperature_update_timestamp = timestamp_sample ;
_temperature_update_timestamp = now ;
}
}
}
@ -319,23 +339,27 @@ void ICM20689::ConfigureSampleRate(int sample_rate)
@@ -319,23 +339,27 @@ void ICM20689::ConfigureSampleRate(int sample_rate)
}
// round down to nearest FIFO sample dt * SAMPLES_PER_TRANSFER
const float min_interval = SAMPLES_PER_TRANSFER * FIFO_SAMPLE_DT ;
const float min_interval = FIFO_SAMPLE_DT * SAMPLES_PER_TRANSFER ;
_fifo_empty_interval_us = math : : max ( roundf ( ( 1e6 f / ( float ) sample_rate ) / min_interval ) * min_interval , min_interval ) ;
_fifo_gyro_samples = math : : min ( ( float ) _fifo_empty_interval_us / ( 1e6 f / GYRO_RATE ) , ( float ) FIFO_MAX_SAMPLES ) ;
_fifo_gyro_samples = roundf ( math : : min ( ( float ) _fifo_empty_interval_us / ( 1e6 f / GYRO_RATE ) , ( float ) FIFO_MAX_SAMPLES ) ) ;
// recompute FIFO empty interval (us) with actual gyro sample limit
_fifo_empty_interval_us = _fifo_gyro_samples * ( 1e6 f / GYRO_RATE ) ;
_fifo_accel_samples = math : : min ( _fifo_empty_interval_us / ( 1e6 f / ACCEL_RATE ) , ( float ) FIFO_MAX_SAMPLES ) ;
}
bool ICM20689 : : Configure ( )
{
// first set and clear all configured register bits
for ( const auto & reg_cfg : _register_cfg ) {
RegisterSetAndClearBits ( reg_cfg . reg , reg_cfg . set_bits , reg_cfg . clear_bits ) ;
}
// now check that all are configured
bool success = true ;
for ( const auto & reg : _register_cfg ) {
if ( ! RegisterCheck ( reg ) ) {
for ( const auto & reg_cfg : _register_cfg ) {
if ( ! RegisterCheck ( reg_cfg ) ) {
success = false ;
}
}
@ -354,12 +378,13 @@ int ICM20689::DataReadyInterruptCallback(int irq, void *context, void *arg)
@@ -354,12 +378,13 @@ int ICM20689::DataReadyInterruptCallback(int irq, void *context, void *arg)
void ICM20689 : : DataReady ( )
{
perf_count ( _drdy_interval_perf ) ;
const uint8_t count = _drdy_count . fetch_add ( 1 ) + 1 ;
if ( _data_ready_count . fetch_add ( 1 ) > = ( _fifo_gyro_samples - 1 ) ) {
_data_ready_count . store ( 0 ) ;
_fifo_watermark_interrupt_timestamp = hrt_absolute_time ( ) ;
_fifo_read_samples . store ( _fifo_gyro_samples ) ;
uint8_t expected = 0 ;
// at least the required number of samples in the FIFO
if ( ( count > = _fifo_gyro_samples ) & & _drdy_fifo_read_samples . compare_exchange ( & expected , _fifo_gyro_samples ) ) {
_drdy_count . store ( 0 ) ;
ScheduleNow ( ) ;
}
}
@ -383,7 +408,7 @@ bool ICM20689::DataReadyInterruptDisable()
@@ -383,7 +408,7 @@ bool ICM20689::DataReadyInterruptDisable()
return px4_arch_gpiosetevent ( _drdy_gpio , false , false , false , nullptr , nullptr ) = = 0 ;
}
bool ICM20689 : : RegisterCheck ( const register_config_t & reg_cfg , bool notify )
bool ICM20689 : : RegisterCheck ( const register_config_t & reg_cfg )
{
bool success = true ;
@ -399,16 +424,6 @@ bool ICM20689::RegisterCheck(const register_config_t ®_cfg, bool notify)
@@ -399,16 +424,6 @@ bool ICM20689::RegisterCheck(const register_config_t ®_cfg, bool notify)
success = false ;
}
if ( ! success ) {
RegisterSetAndClearBits ( reg_cfg . reg , reg_cfg . set_bits , reg_cfg . clear_bits ) ;
if ( notify ) {
perf_count ( _bad_register_perf ) ;
_px4_accel . increase_error_count ( ) ;
_px4_gyro . increase_error_count ( ) ;
}
}
return success ;
}
@ -429,17 +444,12 @@ void ICM20689::RegisterWrite(Register reg, uint8_t value)
@@ -429,17 +444,12 @@ void ICM20689::RegisterWrite(Register reg, uint8_t value)
void ICM20689 : : RegisterSetAndClearBits ( Register reg , uint8_t setbits , uint8_t clearbits )
{
const uint8_t orig_val = RegisterRead ( reg ) ;
uint8_t val = orig_val ;
if ( setbits ) {
val | = setbits ;
}
uint8_t val = ( orig_val & ~ clearbits ) | setbits ;
if ( clearbits ) {
val & = ~ clearbits ;
if ( orig_val ! = val ) {
RegisterWrite ( reg , val ) ;
}
RegisterWrite ( reg , val ) ;
}
uint16_t ICM20689 : : FIFOReadCount ( )
@ -456,11 +466,11 @@ uint16_t ICM20689::FIFOReadCount()
@@ -456,11 +466,11 @@ uint16_t ICM20689::FIFOReadCount()
return combine ( fifo_count_buf [ 1 ] , fifo_count_buf [ 2 ] ) ;
}
bool ICM20689 : : FIFORead ( const hrt_abstime & timestamp_sample , uint16 _t samples )
bool ICM20689 : : FIFORead ( const hrt_abstime & timestamp_sample , uint8 _t samples )
{
perf_begin ( _transfer_perf ) ;
FIFOTransferBuffer buffer { } ;
const size_t transfer_size = math : : min ( samples * sizeof ( FIFO : : DATA ) + 3 , FIFO : : SIZE ) ;
const size_t transfer_size = math : : min ( samples * sizeof ( FIFO : : DATA ) + 1 , FIFO : : SIZE ) ;
if ( transfer ( ( uint8_t * ) & buffer , ( uint8_t * ) & buffer , transfer_size ) ! = PX4_OK ) {
perf_end ( _transfer_perf ) ;
@ -470,47 +480,8 @@ bool ICM20689::FIFORead(const hrt_abstime ×tamp_sample, uint16_t samples)
@@ -470,47 +480,8 @@ bool ICM20689::FIFORead(const hrt_abstime ×tamp_sample, uint16_t samples)
perf_end ( _transfer_perf ) ;
const uint16_t fifo_count_bytes = combine ( buffer . FIFO_COUNTH , buffer . FIFO_COUNTL ) ;
const uint16_t fifo_count_samples = fifo_count_bytes / sizeof ( FIFO : : DATA ) ;
if ( fifo_count_samples = = 0 ) {
perf_count ( _fifo_empty_perf ) ;
return false ;
}
if ( fifo_count_bytes > = FIFO : : SIZE ) {
perf_count ( _fifo_overflow_perf ) ;
FIFOReset ( ) ;
return false ;
}
const uint16_t valid_samples = math : : min ( samples , fifo_count_samples ) ;
if ( fifo_count_samples < samples ) {
// force check if there is somehow fewer samples actually in the FIFO (potentially a serious error)
_force_fifo_count_check = true ;
} else if ( fifo_count_samples > = samples + 2 ) {
// if we're more than a couple samples behind force FIFO_COUNT check
_force_fifo_count_check = true ;
} else {
// skip earlier FIFO_COUNT and trust DRDY count if we're in sync
_force_fifo_count_check = false ;
}
if ( valid_samples > 0 ) {
ProcessGyro ( timestamp_sample , buffer , valid_samples ) ;
if ( ProcessAccel ( timestamp_sample , buffer , valid_samples ) ) {
return true ;
}
}
// force FIFO count check if there was any other error
_force_fifo_count_check = true ;
return false ;
ProcessGyro ( timestamp_sample , buffer . f , samples ) ;
return ProcessAccel ( timestamp_sample , buffer . f , samples ) ;
}
void ICM20689 : : FIFOReset ( )
@ -524,9 +495,8 @@ void ICM20689::FIFOReset()
@@ -524,9 +495,8 @@ void ICM20689::FIFOReset()
RegisterSetAndClearBits ( Register : : USER_CTRL , USER_CTRL_BIT : : FIFO_RST , USER_CTRL_BIT : : FIFO_EN ) ;
// reset while FIFO is disabled
_data_ready_count . store ( 0 ) ;
_fifo_watermark_interrupt_timestamp = 0 ;
_fifo_read_samples . store ( 0 ) ;
_drdy_count . store ( 0 ) ;
_drdy_fifo_read_samples . store ( 0 ) ;
// FIFO_EN: enable both gyro and accel
// USER_CTRL: re-enable FIFO
@ -542,12 +512,12 @@ static bool fifo_accel_equal(const FIFO::DATA &f0, const FIFO::DATA &f1)
@@ -542,12 +512,12 @@ static bool fifo_accel_equal(const FIFO::DATA &f0, const FIFO::DATA &f1)
return ( memcmp ( & f0 . ACCEL_XOUT_H , & f1 . ACCEL_XOUT_H , 6 ) = = 0 ) ;
}
bool ICM20689 : : ProcessAccel ( const hrt_abstime & timestamp_sample , const FIFOTransferBuffer & buffer ,
const uint8_t samples )
bool ICM20689 : : ProcessAccel ( const hrt_abstime & timestamp_sample , const FIFO : : DATA fifo [ ] , const uint8_t samples )
{
PX4Accelerometer : : FIFOSample accel ;
accel . timestamp_sample = timestamp_sample ;
accel . dt = _fifo_empty_interval_us / _fifo_accel_samples ;
accel . samples = 0 ;
accel . dt = FIFO_SAMPLE_DT * SAMPLES_PER_TRANSFER ;
bool bad_data = false ;
@ -555,58 +525,57 @@ bool ICM20689::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTrans
@@ -555,58 +525,57 @@ bool ICM20689::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTrans
int accel_first_sample = 1 ;
if ( samples > = 4 ) {
if ( fifo_accel_equal ( buffer . f [ 0 ] , buffer . f [ 1 ] ) & & fifo_accel_equal ( buffer . f [ 2 ] , buffer . f [ 3 ] ) ) {
if ( fifo_accel_equal ( fifo [ 0 ] , fifo [ 1 ] ) & & fifo_accel_equal ( fifo [ 2 ] , fifo [ 3 ] ) ) {
// [A0, A1, A2, A3]
// A0==A1, A2==A3
accel_first_sample = 1 ;
} else if ( fifo_accel_equal ( buffer . f [ 1 ] , buffer . f [ 2 ] ) ) {
} else if ( fifo_accel_equal ( fifo [ 1 ] , fifo [ 2 ] ) ) {
// [A0, A1, A2, A3]
// A0, A1==A2, A3
accel_first_sample = 0 ;
} else {
perf_count ( _bad_transfer_perf ) ;
// no matching accel samples is an error
bad_data = true ;
perf_count ( _bad_transfer_perf ) ;
}
}
int accel_samples = 0 ;
for ( int i = accel_first_sample ; i < samples ; i = i + 2 ) {
const FIFO : : DATA & fifo_sample = buffer . f [ i ] ;
int16_t accel_x = combine ( fifo_sample . ACCEL_XOUT_H , fifo_sample . ACCEL_XOUT_L ) ;
int16_t accel_y = combine ( fifo_sample . ACCEL_YOUT_H , fifo_sample . ACCEL_YOUT_L ) ;
int16_t accel_z = combine ( fifo_sample . ACCEL_ZOUT_H , fifo_sample . ACCEL_ZOUT_L ) ;
for ( int i = accel_first_sample ; i < samples ; i = i + SAMPLES_PER_TRANSFER ) {
int16_t accel_x = combine ( fifo [ i ] . ACCEL_XOUT_H , fifo [ i ] . ACCEL_XOUT_L ) ;
int16_t accel_y = combine ( fifo [ i ] . ACCEL_YOUT_H , fifo [ i ] . ACCEL_YOUT_L ) ;
int16_t accel_z = combine ( fifo [ i ] . ACCEL_ZOUT_H , fifo [ i ] . ACCEL_ZOUT_L ) ;
// sensor's frame is +x forward, +y left, +z up
// flip y & z to publish right handed with z down (x forward, y right, z down)
accel . x [ accel_ samples ] = accel_x ;
accel . y [ accel_ samples ] = ( accel_y = = INT16_MIN ) ? INT16_MAX : - accel_y ;
accel . z [ accel_ samples ] = ( accel_z = = INT16_MIN ) ? INT16_MAX : - accel_z ;
accel_ samples + + ;
accel . x [ accel . samples ] = accel_x ;
accel . y [ accel . samples ] = ( accel_y = = INT16_MIN ) ? INT16_MAX : - accel_y ;
accel . z [ accel . samples ] = ( accel_z = = INT16_MIN ) ? INT16_MAX : - accel_z ;
accel . samples + + ;
}
accel . samples = accel_samples ;
_px4_accel . set_error_count ( perf_event_count ( _bad_register_perf ) + perf_event_count ( _bad_transfer_perf ) +
perf_event_count ( _fifo_empty_perf ) + perf_event_count ( _fifo_overflow_perf ) ) ;
_px4_accel . updateFIFO ( accel ) ;
if ( accel . samples > 0 ) {
_px4_accel . updateFIFO ( accel ) ;
}
return ! bad_data ;
}
void ICM20689 : : ProcessGyro ( const hrt_abstime & timestamp_sample , const FIFOTransferBuffer & buffer , const uint8_t samples )
void ICM20689 : : ProcessGyro ( const hrt_abstime & timestamp_sample , const FIFO : : DATA fifo [ ] , const uint8_t samples )
{
PX4Gyroscope : : FIFOSample gyro ;
gyro . timestamp_sample = timestamp_sample ;
gyro . samples = samples ;
gyro . dt = _fifo_empty_interval_us / _fifo_gyro_samples ;
gyro . dt = FIFO_SAMPLE_DT ;
for ( int i = 0 ; i < samples ; i + + ) {
const FIFO : : DATA & fifo_sample = buffer . f [ i ] ;
const int16_t gyro_x = combine ( fifo_sample . GYRO_XOUT_H , fifo_sample . GYRO_XOUT_L ) ;
const int16_t gyro_y = combine ( fifo_sample . GYRO_YOUT_H , fifo_sample . GYRO_YOUT_L ) ;
const int16_t gyro_z = combine ( fifo_sample . GYRO_ZOUT_H , fifo_sample . GYRO_ZOUT_L ) ;
const int16_t gyro_x = combine ( fifo [ i ] . GYRO_XOUT_H , fifo [ i ] . GYRO_XOUT_L ) ;
const int16_t gyro_y = combine ( fifo [ i ] . GYRO_YOUT_H , fifo [ i ] . GYRO_YOUT_L ) ;
const int16_t gyro_z = combine ( fifo [ i ] . GYRO_ZOUT_H , fifo [ i ] . GYRO_ZOUT_L ) ;
// sensor's frame is +x forward, +y left, +z up
// flip y & z to publish right handed with z down (x forward, y right, z down)
@ -615,6 +584,9 @@ void ICM20689::ProcessGyro(const hrt_abstime ×tamp_sample, const FIFOTransf
@@ -615,6 +584,9 @@ void ICM20689::ProcessGyro(const hrt_abstime ×tamp_sample, const FIFOTransf
gyro . z [ i ] = ( gyro_z = = INT16_MIN ) ? INT16_MAX : - gyro_z ;
}
_px4_gyro . set_error_count ( perf_event_count ( _bad_register_perf ) + perf_event_count ( _bad_transfer_perf ) +
perf_event_count ( _fifo_empty_perf ) + perf_event_count ( _fifo_overflow_perf ) ) ;
_px4_gyro . updateFIFO ( gyro ) ;
}