|
|
|
@ -20,14 +20,13 @@
@@ -20,14 +20,13 @@
|
|
|
|
|
|
|
|
|
|
#include "AP_InertialSensor_ADIS1647x.h" |
|
|
|
|
|
|
|
|
|
#define BACKEND_SAMPLE_RATE 2000 |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
device registers |
|
|
|
|
*/ |
|
|
|
|
#define REG_PROD_ID 0x72 |
|
|
|
|
#define PROD_ID_16470 0x4056 |
|
|
|
|
#define PROD_ID_16477 0x405d |
|
|
|
|
#define PROD_ID_16507 0x407b |
|
|
|
|
|
|
|
|
|
#define REG_GLOB_CMD 0x68 |
|
|
|
|
#define GLOB_CMD_SW_RESET 0x80 |
|
|
|
@ -36,11 +35,28 @@
@@ -36,11 +35,28 @@
|
|
|
|
|
|
|
|
|
|
#define REG_DATA_CNTR 0x22 |
|
|
|
|
|
|
|
|
|
#define REG_MSC_CTRL 0x60 |
|
|
|
|
# define REG_MSC_CTRL_BURST32 0x200 |
|
|
|
|
# define REG_MSC_CTRL_BURSTSEL 0x100 |
|
|
|
|
# define REG_MSC_CTRL_GCOMP 0x080 |
|
|
|
|
# define REG_MSC_CTRL_PCOMP 0x040 |
|
|
|
|
# define REG_MSC_CTRL_SENSBW 0x010 |
|
|
|
|
# define REG_MSC_CTRL_DRPOL 0x001 |
|
|
|
|
|
|
|
|
|
#define REG_DEC_RATE 0x64 |
|
|
|
|
# define REG_DEC_RATE_2000Hz 0 |
|
|
|
|
# define REG_DEC_RATE_1000Hz 1 |
|
|
|
|
# define REG_DEC_RATE_666Hz 2 |
|
|
|
|
# define REG_DEC_RATE_500Hz 3 |
|
|
|
|
# define REG_DEC_RATE_400Hz 4 |
|
|
|
|
|
|
|
|
|
#define REG_FILT_CTRL 0x5c |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
timings |
|
|
|
|
*/ |
|
|
|
|
#define T_STALL_US 20U |
|
|
|
|
#define T_RESET_MS 250U |
|
|
|
|
#define T_RESET_MS 500U |
|
|
|
|
|
|
|
|
|
#define TIMING_DEBUG 0 |
|
|
|
|
#if TIMING_DEBUG |
|
|
|
@ -89,8 +105,8 @@ AP_InertialSensor_ADIS1647x::probe(AP_InertialSensor &imu,
@@ -89,8 +105,8 @@ AP_InertialSensor_ADIS1647x::probe(AP_InertialSensor &imu,
|
|
|
|
|
|
|
|
|
|
void AP_InertialSensor_ADIS1647x::start() |
|
|
|
|
{ |
|
|
|
|
if (!_imu.register_accel(accel_instance, BACKEND_SAMPLE_RATE, dev->get_bus_id_devtype(DEVTYPE_INS_ADIS1647X)) || |
|
|
|
|
!_imu.register_gyro(gyro_instance, BACKEND_SAMPLE_RATE, dev->get_bus_id_devtype(DEVTYPE_INS_ADIS1647X))) { |
|
|
|
|
if (!_imu.register_accel(accel_instance, expected_sample_rate_hz, dev->get_bus_id_devtype(DEVTYPE_INS_ADIS1647X)) || |
|
|
|
|
!_imu.register_gyro(gyro_instance, expected_sample_rate_hz, dev->get_bus_id_devtype(DEVTYPE_INS_ADIS1647X))) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -113,21 +129,25 @@ void AP_InertialSensor_ADIS1647x::start()
@@ -113,21 +129,25 @@ void AP_InertialSensor_ADIS1647x::start()
|
|
|
|
|
/*
|
|
|
|
|
check product ID |
|
|
|
|
*/ |
|
|
|
|
bool AP_InertialSensor_ADIS1647x::check_product_id(void) |
|
|
|
|
bool AP_InertialSensor_ADIS1647x::check_product_id(uint16_t &prod_id) |
|
|
|
|
{ |
|
|
|
|
uint16_t prod_id = read_reg16(REG_PROD_ID); |
|
|
|
|
prod_id = read_reg16(REG_PROD_ID); |
|
|
|
|
switch (prod_id) { |
|
|
|
|
case PROD_ID_16470: |
|
|
|
|
// can do up to 40G
|
|
|
|
|
opmode = OpMode::Basic; |
|
|
|
|
accel_scale = 1.25 * GRAVITY_MSS * 0.001; |
|
|
|
|
_clip_limit = 39.5f * GRAVITY_MSS; |
|
|
|
|
gyro_scale = radians(0.1); |
|
|
|
|
expected_sample_rate_hz = 2000; |
|
|
|
|
return true; |
|
|
|
|
|
|
|
|
|
case PROD_ID_16477: |
|
|
|
|
case PROD_ID_16477: { |
|
|
|
|
// can do up to 40G
|
|
|
|
|
opmode = OpMode::Basic; |
|
|
|
|
accel_scale = 1.25 * GRAVITY_MSS * 0.001; |
|
|
|
|
_clip_limit = 39.5f * GRAVITY_MSS; |
|
|
|
|
expected_sample_rate_hz = 2000; |
|
|
|
|
// RANG_MDL register used for gyro range
|
|
|
|
|
uint16_t rang_mdl = read_reg16(REG_RANG_MDL); |
|
|
|
|
switch ((rang_mdl >> 2) & 3) { |
|
|
|
@ -145,6 +165,39 @@ bool AP_InertialSensor_ADIS1647x::check_product_id(void)
@@ -145,6 +165,39 @@ bool AP_InertialSensor_ADIS1647x::check_product_id(void)
|
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
case PROD_ID_16507: { |
|
|
|
|
opmode = OpMode::Delta32; |
|
|
|
|
expected_sample_rate_hz = 1200; |
|
|
|
|
accel_scale = 392.0 / 2097152000.0; |
|
|
|
|
dvel_scale = 400.0 / 0x7FFFFFFF; |
|
|
|
|
_clip_limit = 39.5f * GRAVITY_MSS; |
|
|
|
|
// RANG_MDL register used for gyro range
|
|
|
|
|
uint16_t rang_mdl = read_reg16(REG_RANG_MDL); |
|
|
|
|
switch ((rang_mdl >> 2) & 3) { |
|
|
|
|
case 0: |
|
|
|
|
gyro_scale = radians(125) / 0x4E200000; |
|
|
|
|
dangle_scale = radians(360.0 / 0x7FFFFFFF); |
|
|
|
|
break; |
|
|
|
|
case 1: |
|
|
|
|
gyro_scale = radians(500) / 0x4E200000; |
|
|
|
|
dangle_scale = radians(720.0 / 0x7FFFFFFF); |
|
|
|
|
break; |
|
|
|
|
case 3: |
|
|
|
|
gyro_scale = radians(2000) / 0x4E200000; |
|
|
|
|
dangle_scale = radians(2160.0 / 0x7FFFFFFF); |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
if (opmode == OpMode::Basic) { |
|
|
|
|
accel_scale *= 0x10000; |
|
|
|
|
gyro_scale *= 0x10000; |
|
|
|
|
} |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -152,20 +205,52 @@ bool AP_InertialSensor_ADIS1647x::check_product_id(void)
@@ -152,20 +205,52 @@ bool AP_InertialSensor_ADIS1647x::check_product_id(void)
|
|
|
|
|
bool AP_InertialSensor_ADIS1647x::init() |
|
|
|
|
{ |
|
|
|
|
WITH_SEMAPHORE(dev->get_semaphore()); |
|
|
|
|
if (!check_product_id()) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
uint8_t tries = 10; |
|
|
|
|
uint16_t prod_id = 0; |
|
|
|
|
do { |
|
|
|
|
// perform software reset
|
|
|
|
|
write_reg16(REG_GLOB_CMD, GLOB_CMD_SW_RESET); |
|
|
|
|
hal.scheduler->delay(100); |
|
|
|
|
} while (!check_product_id(prod_id) && --tries); |
|
|
|
|
if (tries == 0) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// perform software reset
|
|
|
|
|
write_reg16(REG_GLOB_CMD, GLOB_CMD_SW_RESET); |
|
|
|
|
hal.scheduler->delay(T_RESET_MS); |
|
|
|
|
// bring rate down
|
|
|
|
|
if (expected_sample_rate_hz < 450) { |
|
|
|
|
if (!write_reg16(REG_DEC_RATE, REG_DEC_RATE_400Hz, true)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} else if (expected_sample_rate_hz < 600) { |
|
|
|
|
if (!write_reg16(REG_DEC_RATE, REG_DEC_RATE_500Hz, true)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} else if (expected_sample_rate_hz < 700) { |
|
|
|
|
if (!write_reg16(REG_DEC_RATE, REG_DEC_RATE_666Hz, true)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} else if (expected_sample_rate_hz < 1500) { |
|
|
|
|
if (!write_reg16(REG_DEC_RATE, REG_DEC_RATE_1000Hz, true)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// re-check after reset
|
|
|
|
|
if (!check_product_id()) { |
|
|
|
|
if (!write_reg16(REG_FILT_CTRL, 0, true)) { |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// we leave all config registers at defaults
|
|
|
|
|
// choose burst type and compensation
|
|
|
|
|
uint16_t msc_ctrl = REG_MSC_CTRL_GCOMP | REG_MSC_CTRL_PCOMP | REG_MSC_CTRL_DRPOL; |
|
|
|
|
if (opmode == OpMode::Delta32) { |
|
|
|
|
msc_ctrl |= REG_MSC_CTRL_BURST32 | REG_MSC_CTRL_BURSTSEL; |
|
|
|
|
} else if (opmode == OpMode::AG32) { |
|
|
|
|
msc_ctrl |= REG_MSC_CTRL_BURST32; |
|
|
|
|
} |
|
|
|
|
if (!write_reg16(REG_MSC_CTRL, msc_ctrl, true)) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#if TIMING_DEBUG |
|
|
|
|
// useful for debugging scheduling of transfers
|
|
|
|
@ -200,24 +285,32 @@ uint16_t AP_InertialSensor_ADIS1647x::read_reg16(uint8_t regnum) const
@@ -200,24 +285,32 @@ uint16_t AP_InertialSensor_ADIS1647x::read_reg16(uint8_t regnum) const
|
|
|
|
|
/*
|
|
|
|
|
write a 16 bit register value |
|
|
|
|
*/ |
|
|
|
|
void AP_InertialSensor_ADIS1647x::write_reg16(uint8_t regnum, uint16_t value) const |
|
|
|
|
bool AP_InertialSensor_ADIS1647x::write_reg16(uint8_t regnum, uint16_t value, bool confirm) const |
|
|
|
|
{ |
|
|
|
|
uint8_t req[2]; |
|
|
|
|
req[0] = (regnum | 0x80); |
|
|
|
|
req[1] = value & 0xFF; |
|
|
|
|
dev->transfer(req, sizeof(req), nullptr, 0); |
|
|
|
|
hal.scheduler->delay_microseconds(T_STALL_US); |
|
|
|
|
|
|
|
|
|
req[0] = ((regnum+1) | 0x80); |
|
|
|
|
req[1] = (value>>8) & 0xFF; |
|
|
|
|
dev->transfer(req, sizeof(req), nullptr, 0); |
|
|
|
|
hal.scheduler->delay_microseconds(T_STALL_US); |
|
|
|
|
const uint8_t retries = 16; |
|
|
|
|
for (uint8_t i=0; i<retries; i++) { |
|
|
|
|
uint8_t req[2]; |
|
|
|
|
req[0] = (regnum | 0x80); |
|
|
|
|
req[1] = value & 0xFF; |
|
|
|
|
dev->transfer(req, sizeof(req), nullptr, 0); |
|
|
|
|
hal.scheduler->delay_microseconds(T_STALL_US); |
|
|
|
|
|
|
|
|
|
req[0] = ((regnum+1) | 0x80); |
|
|
|
|
req[1] = (value>>8) & 0xFF; |
|
|
|
|
dev->transfer(req, sizeof(req), nullptr, 0); |
|
|
|
|
hal.scheduler->delay_microseconds(T_STALL_US); |
|
|
|
|
|
|
|
|
|
if (!confirm || read_reg16(regnum) == value) { |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
loop to read the sensor |
|
|
|
|
read the sensor using 16 bit burst transfer of gyro/accel data |
|
|
|
|
*/ |
|
|
|
|
void AP_InertialSensor_ADIS1647x::read_sensor(void) |
|
|
|
|
void AP_InertialSensor_ADIS1647x::read_sensor16(void) |
|
|
|
|
{ |
|
|
|
|
struct adis_data { |
|
|
|
|
uint8_t cmd[2]; |
|
|
|
@ -234,7 +327,6 @@ void AP_InertialSensor_ADIS1647x::read_sensor(void)
@@ -234,7 +327,6 @@ void AP_InertialSensor_ADIS1647x::read_sensor(void)
|
|
|
|
|
uint8_t checksum; |
|
|
|
|
} data {}; |
|
|
|
|
|
|
|
|
|
uint64_t sample_start_us = AP_HAL::micros64(); |
|
|
|
|
do { |
|
|
|
|
WITH_SEMAPHORE(dev->get_semaphore()); |
|
|
|
|
data.cmd[0] = REG_GLOB_CMD; |
|
|
|
@ -281,10 +373,196 @@ void AP_InertialSensor_ADIS1647x::read_sensor(void)
@@ -281,10 +373,196 @@ void AP_InertialSensor_ADIS1647x::read_sensor(void)
|
|
|
|
|
gyro *= gyro_scale; |
|
|
|
|
|
|
|
|
|
_rotate_and_correct_accel(accel_instance, accel); |
|
|
|
|
_notify_new_accel_raw_sample(accel_instance, accel, sample_start_us); |
|
|
|
|
_notify_new_accel_raw_sample(accel_instance, accel); |
|
|
|
|
|
|
|
|
|
_rotate_and_correct_gyro(gyro_instance, gyro); |
|
|
|
|
_notify_new_gyro_raw_sample(gyro_instance, gyro); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
publish average temperature at 20Hz |
|
|
|
|
*/ |
|
|
|
|
temp_sum += float(int16_t(be16toh(data.temp))*0.1); |
|
|
|
|
temp_count++; |
|
|
|
|
|
|
|
|
|
if (temp_count == 100) { |
|
|
|
|
_publish_temperature(accel_instance, temp_sum/temp_count); |
|
|
|
|
temp_sum = 0; |
|
|
|
|
temp_count = 0; |
|
|
|
|
} |
|
|
|
|
DEBUG_SET_PIN(1, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
read the sensor using 32 bit burst transfer of accel/gyro |
|
|
|
|
*/ |
|
|
|
|
void AP_InertialSensor_ADIS1647x::read_sensor32(void) |
|
|
|
|
{ |
|
|
|
|
struct adis_data { |
|
|
|
|
uint8_t cmd[2]; |
|
|
|
|
uint16_t diag_stat; |
|
|
|
|
uint16_t gx_low; |
|
|
|
|
uint16_t gx_high; |
|
|
|
|
uint16_t gy_low; |
|
|
|
|
uint16_t gy_high; |
|
|
|
|
uint16_t gz_low; |
|
|
|
|
uint16_t gz_high; |
|
|
|
|
uint16_t ax_low; |
|
|
|
|
uint16_t ax_high; |
|
|
|
|
uint16_t ay_low; |
|
|
|
|
uint16_t ay_high; |
|
|
|
|
uint16_t az_low; |
|
|
|
|
uint16_t az_high; |
|
|
|
|
uint16_t temp; |
|
|
|
|
uint16_t counter; |
|
|
|
|
uint8_t pad; |
|
|
|
|
uint8_t checksum; |
|
|
|
|
} data {}; |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
WITH_SEMAPHORE(dev->get_semaphore()); |
|
|
|
|
data.cmd[0] = REG_GLOB_CMD; |
|
|
|
|
DEBUG_SET_PIN(2, 1); |
|
|
|
|
if (!dev->transfer((const uint8_t *)&data, sizeof(data), (uint8_t *)&data, sizeof(data))) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
DEBUG_SET_PIN(2, 0); |
|
|
|
|
} while (be16toh(data.counter) == last_counter); |
|
|
|
|
|
|
|
|
|
DEBUG_SET_PIN(1, 1); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
check the 8 bit checksum of the packet |
|
|
|
|
*/ |
|
|
|
|
uint8_t sum = 0; |
|
|
|
|
const uint8_t *b = (const uint8_t *)&data.diag_stat; |
|
|
|
|
for (uint8_t i=0; i<offsetof(adis_data, pad) - offsetof(adis_data, diag_stat); i++) { |
|
|
|
|
sum += b[i]; |
|
|
|
|
} |
|
|
|
|
if (sum != data.checksum) { |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
// corrupt data
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
check if we have lost a sample |
|
|
|
|
*/ |
|
|
|
|
uint16_t counter = be16toh(data.counter); |
|
|
|
|
if (done_first_read && uint16_t(last_counter+1) != counter) { |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
} |
|
|
|
|
done_first_read = true; |
|
|
|
|
last_counter = counter; |
|
|
|
|
|
|
|
|
|
Vector3f accel{float(accel_scale*int32_t(be16toh(data.ax_low) | (be16toh(data.ax_high)<<16))), |
|
|
|
|
-float(accel_scale*int32_t(be16toh(data.ay_low) | (be16toh(data.ay_high)<<16))), |
|
|
|
|
-float(accel_scale*int32_t(be16toh(data.az_low) | (be16toh(data.az_high)<<16)))}; |
|
|
|
|
Vector3f gyro{float(gyro_scale*int32_t(be16toh(data.gx_low) | (be16toh(data.gx_high)<<16))), |
|
|
|
|
-float(gyro_scale*int32_t(be16toh(data.gy_low) | (be16toh(data.gy_high)<<16))), |
|
|
|
|
-float(gyro_scale*int32_t(be16toh(data.gz_low) | (be16toh(data.gz_high)<<16)))}; |
|
|
|
|
|
|
|
|
|
_rotate_and_correct_accel(accel_instance, accel); |
|
|
|
|
_notify_new_accel_raw_sample(accel_instance, accel); |
|
|
|
|
|
|
|
|
|
_rotate_and_correct_gyro(gyro_instance, gyro); |
|
|
|
|
_notify_new_gyro_raw_sample(gyro_instance, gyro, sample_start_us); |
|
|
|
|
_notify_new_gyro_raw_sample(gyro_instance, gyro); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
publish average temperature at 20Hz |
|
|
|
|
*/ |
|
|
|
|
temp_sum += float(int16_t(be16toh(data.temp))*0.1); |
|
|
|
|
temp_count++; |
|
|
|
|
|
|
|
|
|
if (temp_count == 100) { |
|
|
|
|
_publish_temperature(accel_instance, temp_sum/temp_count); |
|
|
|
|
temp_sum = 0; |
|
|
|
|
temp_count = 0; |
|
|
|
|
} |
|
|
|
|
DEBUG_SET_PIN(1, 0); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
read the sensor using 32 bit burst transfer of delta-angle/delta-velocity |
|
|
|
|
*/ |
|
|
|
|
void AP_InertialSensor_ADIS1647x::read_sensor32_delta(void) |
|
|
|
|
{ |
|
|
|
|
struct adis_data { |
|
|
|
|
uint8_t cmd[2]; |
|
|
|
|
uint16_t diag_stat; |
|
|
|
|
uint16_t dax_low; |
|
|
|
|
uint16_t dax_high; |
|
|
|
|
uint16_t day_low; |
|
|
|
|
uint16_t day_high; |
|
|
|
|
uint16_t daz_low; |
|
|
|
|
uint16_t daz_high; |
|
|
|
|
uint16_t dvx_low; |
|
|
|
|
uint16_t dvx_high; |
|
|
|
|
uint16_t dvy_low; |
|
|
|
|
uint16_t dvy_high; |
|
|
|
|
uint16_t dvz_low; |
|
|
|
|
uint16_t dvz_high; |
|
|
|
|
uint16_t temp; |
|
|
|
|
uint16_t counter; |
|
|
|
|
uint8_t pad; |
|
|
|
|
uint8_t checksum; |
|
|
|
|
} data {}; |
|
|
|
|
|
|
|
|
|
do { |
|
|
|
|
WITH_SEMAPHORE(dev->get_semaphore()); |
|
|
|
|
data.cmd[0] = REG_GLOB_CMD; |
|
|
|
|
DEBUG_SET_PIN(2, 1); |
|
|
|
|
if (!dev->transfer((const uint8_t *)&data, sizeof(data), (uint8_t *)&data, sizeof(data))) { |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
DEBUG_SET_PIN(2, 0); |
|
|
|
|
} while (be16toh(data.counter) == last_counter); |
|
|
|
|
|
|
|
|
|
DEBUG_SET_PIN(1, 1); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
check the 8 bit checksum of the packet |
|
|
|
|
*/ |
|
|
|
|
uint8_t sum = 0; |
|
|
|
|
const uint8_t *b = (const uint8_t *)&data.diag_stat; |
|
|
|
|
for (uint8_t i=0; i<offsetof(adis_data, pad) - offsetof(adis_data, diag_stat); i++) { |
|
|
|
|
sum += b[i]; |
|
|
|
|
} |
|
|
|
|
if (sum != data.checksum) { |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
// corrupt data
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
check if we have lost a sample |
|
|
|
|
*/ |
|
|
|
|
uint16_t counter = be16toh(data.counter); |
|
|
|
|
if (done_first_read && uint16_t(last_counter+1) != counter) { |
|
|
|
|
DEBUG_TOGGLE_PIN(3); |
|
|
|
|
} |
|
|
|
|
done_first_read = true; |
|
|
|
|
last_counter = counter; |
|
|
|
|
|
|
|
|
|
Vector3f dvel{float(dvel_scale*int32_t(be16toh(data.dvx_low) | (be16toh(data.dvx_high)<<16))), |
|
|
|
|
-float(dvel_scale*int32_t(be16toh(data.dvy_low) | (be16toh(data.dvy_high)<<16))), |
|
|
|
|
-float(dvel_scale*int32_t(be16toh(data.dvz_low) | (be16toh(data.dvz_high)<<16)))}; |
|
|
|
|
Vector3f dangle{float(dangle_scale*int32_t(be16toh(data.dax_low) | (be16toh(data.dax_high)<<16))), |
|
|
|
|
-float(dangle_scale*int32_t(be16toh(data.day_low) | (be16toh(data.day_high)<<16))), |
|
|
|
|
-float(dangle_scale*int32_t(be16toh(data.daz_low) | (be16toh(data.daz_high)<<16)))}; |
|
|
|
|
|
|
|
|
|
// compensate for clock errors, see "DELTA ANGLES" in datasheet
|
|
|
|
|
dangle *= expected_sample_rate_hz / _gyro_raw_sample_rate(gyro_instance); |
|
|
|
|
dvel *= expected_sample_rate_hz / _accel_raw_sample_rate(gyro_instance); |
|
|
|
|
|
|
|
|
|
_notify_new_delta_velocity(accel_instance, dvel); |
|
|
|
|
_notify_new_delta_angle(gyro_instance, dangle); |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
publish average temperature at 20Hz |
|
|
|
@ -309,15 +587,21 @@ void AP_InertialSensor_ADIS1647x::loop(void)
@@ -309,15 +587,21 @@ void AP_InertialSensor_ADIS1647x::loop(void)
|
|
|
|
|
uint32_t tstart = AP_HAL::micros(); |
|
|
|
|
// we deliberately set the period a bit fast to ensure we
|
|
|
|
|
// don't lose a sample
|
|
|
|
|
const uint32_t period_us = 480; |
|
|
|
|
const uint32_t period_us = (1000000UL / expected_sample_rate_hz) - 20U; |
|
|
|
|
bool wait_ok = false; |
|
|
|
|
if (drdy_pin != 0) { |
|
|
|
|
// when we have a DRDY pin then wait for it to go high
|
|
|
|
|
DEBUG_SET_PIN(0, 1); |
|
|
|
|
wait_ok = hal.gpio->wait_pin(drdy_pin, AP_HAL::GPIO::INTERRUPT_RISING, 1000); |
|
|
|
|
wait_ok = hal.gpio->wait_pin(drdy_pin, AP_HAL::GPIO::INTERRUPT_RISING, 2100); |
|
|
|
|
DEBUG_SET_PIN(0, 0); |
|
|
|
|
} |
|
|
|
|
read_sensor(); |
|
|
|
|
if (opmode == OpMode::Delta32) { |
|
|
|
|
read_sensor32_delta(); |
|
|
|
|
} else if (opmode == OpMode::AG32) { |
|
|
|
|
read_sensor32(); |
|
|
|
|
} else { |
|
|
|
|
read_sensor16(); |
|
|
|
|
} |
|
|
|
|
uint32_t dt = AP_HAL::micros() - tstart; |
|
|
|
|
if (dt < period_us) { |
|
|
|
|
uint32_t wait_us = period_us - dt; |
|
|
|
|