|
|
|
@ -45,8 +45,8 @@ ICM20602::ICM20602(I2CSPIBusOption bus_option, int bus, uint32_t device, enum Ro
@@ -45,8 +45,8 @@ ICM20602::ICM20602(I2CSPIBusOption bus_option, int bus, uint32_t device, enum Ro
|
|
|
|
|
SPI(MODULE_NAME, nullptr, bus, device, spi_mode, bus_frequency), |
|
|
|
|
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus), |
|
|
|
|
_drdy_gpio(drdy_gpio), |
|
|
|
|
_px4_accel(get_device_id(), ORB_PRIO_VERY_HIGH, rotation), |
|
|
|
|
_px4_gyro(get_device_id(), ORB_PRIO_VERY_HIGH, rotation) |
|
|
|
|
_px4_accel(get_device_id(), ORB_PRIO_HIGH, rotation), |
|
|
|
|
_px4_gyro(get_device_id(), ORB_PRIO_HIGH, rotation) |
|
|
|
|
{ |
|
|
|
|
set_device_type(DRV_IMU_DEVTYPE_ICM20602); |
|
|
|
|
|
|
|
|
@ -131,7 +131,7 @@ void ICM20602::RunImpl()
@@ -131,7 +131,7 @@ void ICM20602::RunImpl()
|
|
|
|
|
RegisterWrite(Register::PWR_MGMT_1, PWR_MGMT_1_BIT::DEVICE_RESET); |
|
|
|
|
_reset_timestamp = hrt_absolute_time(); |
|
|
|
|
_state = STATE::WAIT_FOR_RESET; |
|
|
|
|
ScheduleDelayed(100); |
|
|
|
|
ScheduleDelayed(1_ms); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case STATE::WAIT_FOR_RESET: |
|
|
|
@ -148,14 +148,14 @@ void ICM20602::RunImpl()
@@ -148,14 +148,14 @@ void ICM20602::RunImpl()
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
// RESET not complete
|
|
|
|
|
if (hrt_elapsed_time(&_reset_timestamp) > 10_ms) { |
|
|
|
|
PX4_ERR("Reset failed, retrying"); |
|
|
|
|
if (hrt_elapsed_time(&_reset_timestamp) > 100_ms) { |
|
|
|
|
PX4_DEBUG("Reset failed, retrying"); |
|
|
|
|
_state = STATE::RESET; |
|
|
|
|
ScheduleDelayed(10_ms); |
|
|
|
|
ScheduleDelayed(100_ms); |
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_DEBUG("Reset not complete, check again in 1 ms"); |
|
|
|
|
ScheduleDelayed(1_ms); |
|
|
|
|
PX4_DEBUG("Reset not complete, check again in 10 ms"); |
|
|
|
|
ScheduleDelayed(10_ms); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -181,8 +181,8 @@ void ICM20602::RunImpl()
@@ -181,8 +181,8 @@ void ICM20602::RunImpl()
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
PX4_DEBUG("Configure failed, retrying"); |
|
|
|
|
// try again in 1 ms
|
|
|
|
|
ScheduleDelayed(1_ms); |
|
|
|
|
// try again in 10 ms
|
|
|
|
|
ScheduleDelayed(10_ms); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
break; |
|
|
|
@ -209,13 +209,7 @@ void ICM20602::RunImpl()
@@ -209,13 +209,7 @@ void ICM20602::RunImpl()
|
|
|
|
|
// 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(); |
|
|
|
|
|
|
|
|
|
if (fifo_count == 0) { |
|
|
|
|
failure = true; |
|
|
|
|
perf_count(_fifo_empty_perf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
samples = (fifo_count / sizeof(FIFO::DATA) / 2) * 2; // round down to nearest 2
|
|
|
|
|
samples = (fifo_count / sizeof(FIFO::DATA) / SAMPLES_PER_TRANSFER) * SAMPLES_PER_TRANSFER; // round down to nearest
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (samples > FIFO_MAX_SAMPLES) { |
|
|
|
@ -224,13 +218,17 @@ void ICM20602::RunImpl()
@@ -224,13 +218,17 @@ void ICM20602::RunImpl()
|
|
|
|
|
failure = true; |
|
|
|
|
FIFOReset(); |
|
|
|
|
|
|
|
|
|
} else if (samples >= 2) { |
|
|
|
|
// require at least 2 samples (we want at least 1 new accel sample per transfer)
|
|
|
|
|
} 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(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} else if (samples == 0) { |
|
|
|
|
failure = true; |
|
|
|
|
perf_count(_fifo_empty_perf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (failure || hrt_elapsed_time(&_last_config_check_timestamp) > 10_ms) { |
|
|
|
@ -258,22 +256,22 @@ void ICM20602::ConfigureAccel()
@@ -258,22 +256,22 @@ void ICM20602::ConfigureAccel()
|
|
|
|
|
|
|
|
|
|
switch (ACCEL_FS_SEL) { |
|
|
|
|
case ACCEL_FS_SEL_2G: |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 16384); |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 16384.f); |
|
|
|
|
_px4_accel.set_range(2 * CONSTANTS_ONE_G); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ACCEL_FS_SEL_4G: |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 8192); |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 8192.f); |
|
|
|
|
_px4_accel.set_range(4 * CONSTANTS_ONE_G); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ACCEL_FS_SEL_8G: |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 4096); |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 4096.f); |
|
|
|
|
_px4_accel.set_range(8 * CONSTANTS_ONE_G); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case ACCEL_FS_SEL_16G: |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 2048); |
|
|
|
|
_px4_accel.set_scale(CONSTANTS_ONE_G / 2048.f); |
|
|
|
|
_px4_accel.set_range(16 * CONSTANTS_ONE_G); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
@ -285,23 +283,23 @@ void ICM20602::ConfigureGyro()
@@ -285,23 +283,23 @@ void ICM20602::ConfigureGyro()
|
|
|
|
|
|
|
|
|
|
switch (FS_SEL) { |
|
|
|
|
case FS_SEL_250_DPS: |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.0f / 131.f)); |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.f / 131.f)); |
|
|
|
|
_px4_gyro.set_range(math::radians(250.f)); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FS_SEL_500_DPS: |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.0f / 65.5f)); |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.f / 65.5f)); |
|
|
|
|
_px4_gyro.set_range(math::radians(500.f)); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FS_SEL_1000_DPS: |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.0f / 32.8f)); |
|
|
|
|
_px4_gyro.set_range(math::radians(1000.0f)); |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.f / 32.8f)); |
|
|
|
|
_px4_gyro.set_range(math::radians(1000.f)); |
|
|
|
|
break; |
|
|
|
|
|
|
|
|
|
case FS_SEL_2000_DPS: |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.0f / 16.4f)); |
|
|
|
|
_px4_gyro.set_range(math::radians(2000.0f)); |
|
|
|
|
_px4_gyro.set_scale(math::radians(1.f / 16.4f)); |
|
|
|
|
_px4_gyro.set_range(math::radians(2000.f)); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -312,19 +310,27 @@ void ICM20602::ConfigureSampleRate(int sample_rate)
@@ -312,19 +310,27 @@ void ICM20602::ConfigureSampleRate(int sample_rate)
|
|
|
|
|
sample_rate = 1000; // default to 1 kHz
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
_fifo_empty_interval_us = math::max(((1000000 / sample_rate) / 250) * 250, 250); // round down to nearest 250 us
|
|
|
|
|
_fifo_gyro_samples = math::min(_fifo_empty_interval_us / (1000000 / GYRO_RATE), FIFO_MAX_SAMPLES); |
|
|
|
|
// round down to nearest FIFO sample dt * SAMPLES_PER_TRANSFER
|
|
|
|
|
const float min_interval = SAMPLES_PER_TRANSFER * FIFO_SAMPLE_DT; |
|
|
|
|
_fifo_empty_interval_us = math::max(roundf((1e6f / (float)sample_rate) / min_interval) * min_interval, min_interval); |
|
|
|
|
|
|
|
|
|
_fifo_gyro_samples = math::min((float)_fifo_empty_interval_us / (1e6f / GYRO_RATE), (float)FIFO_MAX_SAMPLES); |
|
|
|
|
|
|
|
|
|
// recompute FIFO empty interval (us) with actual gyro sample limit
|
|
|
|
|
_fifo_empty_interval_us = _fifo_gyro_samples * (1000000 / GYRO_RATE); |
|
|
|
|
_fifo_empty_interval_us = _fifo_gyro_samples * (1e6f / GYRO_RATE); |
|
|
|
|
|
|
|
|
|
_fifo_accel_samples = math::min(_fifo_empty_interval_us / (1000000 / ACCEL_RATE), FIFO_MAX_SAMPLES); |
|
|
|
|
_fifo_accel_samples = math::min(_fifo_empty_interval_us / (1e6f / ACCEL_RATE), (float)FIFO_MAX_SAMPLES); |
|
|
|
|
|
|
|
|
|
_px4_accel.set_update_rate(1000000 / _fifo_empty_interval_us); |
|
|
|
|
_px4_gyro.set_update_rate(1000000 / _fifo_empty_interval_us); |
|
|
|
|
_px4_accel.set_update_rate(1e6f / _fifo_empty_interval_us); |
|
|
|
|
_px4_gyro.set_update_rate(1e6f / _fifo_empty_interval_us); |
|
|
|
|
|
|
|
|
|
ConfigureFIFOWatermark(_fifo_gyro_samples); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ICM20602::ConfigureFIFOWatermark(uint8_t samples) |
|
|
|
|
{ |
|
|
|
|
// FIFO watermark threshold in number of bytes
|
|
|
|
|
const uint16_t fifo_watermark_threshold = _fifo_gyro_samples * sizeof(FIFO::DATA); |
|
|
|
|
const uint16_t fifo_watermark_threshold = samples * sizeof(FIFO::DATA); |
|
|
|
|
|
|
|
|
|
for (auto &r : _register_cfg) { |
|
|
|
|
if (r.reg == Register::FIFO_WM_TH1) { |
|
|
|
@ -360,10 +366,10 @@ int ICM20602::DataReadyInterruptCallback(int irq, void *context, void *arg)
@@ -360,10 +366,10 @@ int ICM20602::DataReadyInterruptCallback(int irq, void *context, void *arg)
|
|
|
|
|
|
|
|
|
|
void ICM20602::DataReady() |
|
|
|
|
{ |
|
|
|
|
perf_count(_drdy_interval_perf); |
|
|
|
|
_fifo_watermark_interrupt_timestamp = hrt_absolute_time(); |
|
|
|
|
_fifo_read_samples.store(_fifo_gyro_samples); |
|
|
|
|
ScheduleNow(); |
|
|
|
|
perf_count(_drdy_interval_perf); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ICM20602::DataReadyInterruptConfigure() |
|
|
|
@ -372,8 +378,8 @@ bool ICM20602::DataReadyInterruptConfigure()
@@ -372,8 +378,8 @@ bool ICM20602::DataReadyInterruptConfigure()
|
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Setup data ready on rising edge
|
|
|
|
|
return px4_arch_gpiosetevent(_drdy_gpio, true, false, true, &ICM20602::DataReadyInterruptCallback, this) == 0; |
|
|
|
|
// Setup data ready on falling edge
|
|
|
|
|
return px4_arch_gpiosetevent(_drdy_gpio, false, true, true, &ICM20602::DataReadyInterruptCallback, this) == 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ICM20602::DataReadyInterruptDisable() |
|
|
|
@ -391,12 +397,12 @@ bool ICM20602::RegisterCheck(const register_config_t ®_cfg, bool notify)
@@ -391,12 +397,12 @@ bool ICM20602::RegisterCheck(const register_config_t ®_cfg, bool notify)
|
|
|
|
|
|
|
|
|
|
const uint8_t reg_value = RegisterRead(reg_cfg.reg); |
|
|
|
|
|
|
|
|
|
if (reg_cfg.set_bits && !(reg_value & reg_cfg.set_bits)) { |
|
|
|
|
if (reg_cfg.set_bits && ((reg_value & reg_cfg.set_bits) != reg_cfg.set_bits)) { |
|
|
|
|
PX4_DEBUG("0x%02hhX: 0x%02hhX (0x%02hhX not set)", (uint8_t)reg_cfg.reg, reg_value, reg_cfg.set_bits); |
|
|
|
|
success = false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (reg_cfg.clear_bits && (reg_value & reg_cfg.clear_bits)) { |
|
|
|
|
if (reg_cfg.clear_bits && ((reg_value & reg_cfg.clear_bits) != 0)) { |
|
|
|
|
PX4_DEBUG("0x%02hhX: 0x%02hhX (0x%02hhX not cleared)", (uint8_t)reg_cfg.reg, reg_value, reg_cfg.clear_bits); |
|
|
|
|
success = false; |
|
|
|
|
} |
|
|
|
@ -404,13 +410,6 @@ bool ICM20602::RegisterCheck(const register_config_t ®_cfg, bool notify)
@@ -404,13 +410,6 @@ bool ICM20602::RegisterCheck(const register_config_t ®_cfg, bool notify)
|
|
|
|
|
if (!success) { |
|
|
|
|
RegisterSetAndClearBits(reg_cfg.reg, reg_cfg.set_bits, reg_cfg.clear_bits); |
|
|
|
|
|
|
|
|
|
if (reg_cfg.reg == Register::ACCEL_CONFIG) { |
|
|
|
|
ConfigureAccel(); |
|
|
|
|
|
|
|
|
|
} else if (reg_cfg.reg == Register::GYRO_CONFIG) { |
|
|
|
|
ConfigureGyro(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (notify) { |
|
|
|
|
perf_count(_bad_register_perf); |
|
|
|
|
_px4_accel.increase_error_count(); |
|
|
|
@ -451,16 +450,6 @@ void ICM20602::RegisterSetAndClearBits(Register reg, uint8_t setbits, uint8_t cl
@@ -451,16 +450,6 @@ void ICM20602::RegisterSetAndClearBits(Register reg, uint8_t setbits, uint8_t cl
|
|
|
|
|
RegisterWrite(reg, val); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ICM20602::RegisterSetBits(Register reg, uint8_t setbits) |
|
|
|
|
{ |
|
|
|
|
RegisterSetAndClearBits(reg, setbits, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ICM20602::RegisterClearBits(Register reg, uint8_t clearbits) |
|
|
|
|
{ |
|
|
|
|
RegisterSetAndClearBits(reg, 0, clearbits); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint16_t ICM20602::FIFOReadCount() |
|
|
|
|
{ |
|
|
|
|
// read FIFO count
|
|
|
|
@ -516,9 +505,8 @@ void ICM20602::FIFOReset()
@@ -516,9 +505,8 @@ void ICM20602::FIFOReset()
|
|
|
|
|
// FIFO_EN: disable FIFO
|
|
|
|
|
RegisterWrite(Register::FIFO_EN, 0); |
|
|
|
|
|
|
|
|
|
// USER_CTRL: disable FIFO and reset all signal paths
|
|
|
|
|
RegisterSetAndClearBits(Register::USER_CTRL, USER_CTRL_BIT::FIFO_RST | USER_CTRL_BIT::SIG_COND_RST, |
|
|
|
|
USER_CTRL_BIT::FIFO_EN); |
|
|
|
|
// USER_CTRL: reset FIFO
|
|
|
|
|
RegisterSetAndClearBits(Register::USER_CTRL, USER_CTRL_BIT::FIFO_RST, USER_CTRL_BIT::FIFO_EN); |
|
|
|
|
|
|
|
|
|
// reset while FIFO is disabled
|
|
|
|
|
_fifo_watermark_interrupt_timestamp = 0; |
|
|
|
@ -538,7 +526,8 @@ static bool fifo_accel_equal(const FIFO::DATA &f0, const FIFO::DATA &f1)
@@ -538,7 +526,8 @@ 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 ICM20602::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTransferBuffer &buffer, uint8_t samples) |
|
|
|
|
bool ICM20602::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTransferBuffer &buffer, |
|
|
|
|
const uint8_t samples) |
|
|
|
|
{ |
|
|
|
|
PX4Accelerometer::FIFOSample accel; |
|
|
|
|
accel.timestamp_sample = timestamp_sample; |
|
|
|
@ -549,8 +538,8 @@ bool ICM20602::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTrans
@@ -549,8 +538,8 @@ bool ICM20602::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTrans
|
|
|
|
|
// accel data is doubled in FIFO, but might be shifted
|
|
|
|
|
int accel_first_sample = 1; |
|
|
|
|
|
|
|
|
|
if (samples >= 3) { |
|
|
|
|
if (fifo_accel_equal(buffer.f[0], buffer.f[1])) { |
|
|
|
|
if (samples >= 4) { |
|
|
|
|
if (fifo_accel_equal(buffer.f[0], buffer.f[1]) && fifo_accel_equal(buffer.f[2], buffer.f[3])) { |
|
|
|
|
// [A0, A1, A2, A3]
|
|
|
|
|
// A0==A1, A2==A3
|
|
|
|
|
accel_first_sample = 1; |
|
|
|
@ -589,7 +578,7 @@ bool ICM20602::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTrans
@@ -589,7 +578,7 @@ bool ICM20602::ProcessAccel(const hrt_abstime ×tamp_sample, const FIFOTrans
|
|
|
|
|
return !bad_data; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void ICM20602::ProcessGyro(const hrt_abstime ×tamp_sample, const FIFOTransferBuffer &buffer, uint8_t samples) |
|
|
|
|
void ICM20602::ProcessGyro(const hrt_abstime ×tamp_sample, const FIFOTransferBuffer &buffer, const uint8_t samples) |
|
|
|
|
{ |
|
|
|
|
PX4Gyroscope::FIFOSample gyro; |
|
|
|
|
gyro.timestamp_sample = timestamp_sample; |
|
|
|
@ -613,7 +602,7 @@ void ICM20602::ProcessGyro(const hrt_abstime ×tamp_sample, const FIFOTransf
@@ -613,7 +602,7 @@ void ICM20602::ProcessGyro(const hrt_abstime ×tamp_sample, const FIFOTransf
|
|
|
|
|
_px4_gyro.updateFIFO(gyro); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
bool ICM20602::ProcessTemperature(const FIFOTransferBuffer &buffer, uint8_t samples) |
|
|
|
|
bool ICM20602::ProcessTemperature(const FIFOTransferBuffer &buffer, const uint8_t samples) |
|
|
|
|
{ |
|
|
|
|
int16_t temperature[samples]; |
|
|
|
|
|
|
|
|
|