PX4 Firmware
PX4 Autopilot Software http://px4.io
ADIS16448.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2018-2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file ADIS16448.cpp
36  */
37 
38 #include "ADIS16448.h"
39 
40 ADIS16448::ADIS16448(int bus, uint32_t device, enum Rotation rotation) :
41  SPI("ADIS16448", nullptr, bus, device, SPIDEV_MODE3, 1000000),
42  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(get_device_id())),
43  _px4_accel(get_device_id(), ORB_PRIO_MAX, rotation),
44  _px4_baro(get_device_id(), ORB_PRIO_MAX),
45  _px4_gyro(get_device_id(), ORB_PRIO_MAX, rotation),
46  _px4_mag(get_device_id(), ORB_PRIO_MAX, rotation)
47 {
49  _px4_baro.set_device_type(DRV_ACC_DEVTYPE_ADIS16448); // not a typo, baro uses accel device id
52 
56 
57  _px4_mag.set_external(external());
58 }
59 
61 {
62  // Ensure the driver is inactive.
63  stop();
64 
65  // Delete the perf counter.
70 }
71 
72 int
74 {
75  // Do SPI init (and probe) first.
76  int ret = SPI::init();
77 
78  if (ret != PX4_OK) {
79  DEVICE_DEBUG("SPI setup failed %d", ret);
80 
81  // If probe/setup failed, return result.
82  return ret;
83  }
84 
85  ret = measure();
86 
87  if (ret != PX4_OK) {
88  PX4_ERR("measure failed");
89  return PX4_ERROR;
90  }
91 
92  start();
93 
94  return OK;
95 }
96 
98 {
99  // Software reset
100  write_reg16(ADIS16448_GLOB_CMD, 1 << 7); // GLOB_CMD bit 7 Software reset
101 
102  // Reset Recovery Time 90 ms
103  usleep(90000);
104 
105  if (!self_test()) {
106  return false;
107  }
108 
109  // Factory calibration restore
110  //write_reg16(ADIS16448_GLOB_CMD, 1 << 1); // GLOB_CMD bit 1 Factory calibration restore
111 
112  // include the CRC-16 code in burst read output sequence
114 
115  // Set digital FIR filter tap.
116  //if (!set_dlpf_filter(BITS_FIR_NO_TAP_CFG)) {
117  // return PX4_ERROR;
118  //}
119 
120  // Set IMU sample rate.
122  return false;
123  }
124 
125  // Set gyroscope scale to default value.
126  //if (!set_gyro_dyn_range(GYRO_INITIAL_SENSITIVITY)) {
127  // return false;
128  //}
129 
130  // Settling time.
131  usleep(100000);
132 
133  return true;
134 }
135 
137 {
138  bool ret = true;
139 
140  // start internal self test routine
141  write_reg16(ADIS16448_MSC_CTRL, 0x04); // MSC_CTRL bit 10 Internal self test (cleared upon completion)
142 
143  // Automatic Self-Test Time 45 ms
144  usleep(45000);
145 
146  // check test status (ADIS16448_DIAG_STAT)
147  const uint16_t status = read_reg16(ADIS16448_DIAG_STAT);
148 
149  const bool self_test_error = (status & (1 << 5)); // 5: Self-test diagnostic error flag
150 
151  if (self_test_error) {
152  //PX4_ERR("self test failed DIAG_STAT: 0x%04X", status);
153 
154  // Magnetometer
155  const bool mag_fail = (status & (1 << 0)); // 0: Magnetometer functional test
156 
157  if (mag_fail) {
158  // tolerate mag test failure (likely due to surrounding magnetic field)
159  PX4_WARN("Magnetometer functional test fail");
160  }
161 
162  // Barometer
163  const bool baro_fail = (status & (1 << 1)); // 1: Barometer functional test
164 
165  if (baro_fail) {
166  PX4_ERR("Barometer functional test test fail");
167  ret = false;
168  }
169 
170  // Gyroscope
171  const bool gyro_x_fail = (status & (1 << 10)); // 10: X-axis gyroscope self-test failure
172  const bool gyro_y_fail = (status & (1 << 11)); // 11: Y-axis gyroscope self-test failure
173  const bool gyro_z_fail = (status & (1 << 12)); // 12: Z-axis gyroscope self-test failure
174 
175  if (gyro_x_fail || gyro_y_fail || gyro_z_fail) {
176  PX4_ERR("gyroscope self-test failure");
177  ret = false;
178  }
179 
180  // Accelerometer
181  const bool accel_x_fail = (status & (1 << 13)); // 13: X-axis accelerometer self-test failure
182  const bool accel_y_fail = (status & (1 << 14)); // 14: Y-axis accelerometer self-test failure
183  const bool accel_z_fail = (status & (1 << 15)); // 15: Z-axis accelerometer self-test failure
184 
185  if (accel_x_fail || accel_y_fail || accel_z_fail) {
186  PX4_ERR("accelerometer self-test failure");
187  ret = false;
188  }
189  }
190 
191  return ret;
192 }
193 
194 int
196 {
197  bool reset_success = reset();
198 
199  // Retry 5 time to get the ADIS16448 PRODUCT ID number.
200  for (size_t i = 0; i < 5; i++) {
201  // Read product ID.
203 
205  break;
206  }
207 
208  reset_success = reset();
209  }
210 
211  if (!reset_success) {
212  PX4_ERR("unable to successfully reset");
213  return PX4_ERROR;
214  }
215 
216  // Recognize product serial number.
217  uint16_t serial_number = (read_reg16(ADIS16334_SERIAL_NUMBER) & 0xfff);
218 
219  // Verify product ID.
220  switch (_product_ID) {
221  case ADIS16448_Product:
222  DEVICE_DEBUG("ADIS16448 is detected ID: 0x%02x, Serial: 0x%02x", _product_ID, serial_number);
223  modify_reg16(ADIS16448_GPIO_CTRL, 0x0200, 0x0002); // Turn on ADIS16448 adaptor board led.
224  return OK;
225  }
226 
227  DEVICE_DEBUG("unexpected ID 0x%02x", _product_ID);
228 
229  return -EIO;
230 }
231 
232 bool
233 ADIS16448::set_sample_rate(uint16_t desired_sample_rate_hz)
234 {
235  uint16_t smpl_prd = 0;
236 
237  if (desired_sample_rate_hz <= 51) {
238  smpl_prd = BITS_SMPL_PRD_16_TAP_CFG;
239 
240  } else if (desired_sample_rate_hz <= 102) {
241  smpl_prd = BITS_SMPL_PRD_8_TAP_CFG;
242 
243  } else if (desired_sample_rate_hz <= 204) {
244  smpl_prd = BITS_SMPL_PRD_4_TAP_CFG;
245 
246  } else if (desired_sample_rate_hz <= 409) {
247  smpl_prd = BITS_SMPL_PRD_2_TAP_CFG;
248 
249  } else {
250  smpl_prd = BITS_SMPL_PRD_NO_TAP_CFG;
251  }
252 
253  modify_reg16(ADIS16448_SMPL_PRD, 0x1F00, smpl_prd);
254 
255  if ((read_reg16(ADIS16448_SMPL_PRD) & 0x1F00) != smpl_prd) {
256  PX4_ERR("failed to set IMU sample rate");
257 
258  return false;
259  }
260 
261  _px4_accel.set_sample_rate(desired_sample_rate_hz);
262  _px4_gyro.set_sample_rate(desired_sample_rate_hz);
263 
264  return true;
265 }
266 
267 bool
268 ADIS16448::set_dlpf_filter(uint16_t desired_filter_tap)
269 {
270  // Set the DLPF FIR filter tap. This affects both accelerometer and gyroscope.
271  modify_reg16(ADIS16448_SENS_AVG, 0x0007, desired_filter_tap);
272 
273  // Verify data write on the IMU.
274  if ((read_reg16(ADIS16448_SENS_AVG) & 0x0007) != desired_filter_tap) {
275  PX4_ERR("failed to set IMU filter");
276 
277  return false;
278  }
279 
280  return true;
281 }
282 
283 bool
284 ADIS16448::set_gyro_dyn_range(uint16_t desired_gyro_dyn_range)
285 {
286  uint16_t gyro_range_selection = 0;
287 
288  if (desired_gyro_dyn_range <= 250) {
289  gyro_range_selection = BITS_GYRO_DYN_RANGE_250_CFG;
290 
291  } else if (desired_gyro_dyn_range <= 500) {
292  gyro_range_selection = BITS_GYRO_DYN_RANGE_500_CFG;
293 
294  } else {
295  gyro_range_selection = BITS_GYRO_DYN_RANGE_1000_CFG;
296  }
297 
298  modify_reg16(ADIS16448_SENS_AVG, 0x0700, gyro_range_selection);
299 
300  // Verify data write on the IMU.
301  if ((read_reg16(ADIS16448_SENS_AVG) & 0x0700) != gyro_range_selection) {
302  PX4_ERR("failed to set gyro range");
303  return false;
304 
305  } else {
306  _px4_gyro.set_scale(((gyro_range_selection >> 8) / 100.0f) * M_PI_F / 180.0f);
307  }
308 
309  return true;
310 }
311 
312 void
314 {
319 
324 }
325 
326 void
327 ADIS16448::modify_reg16(unsigned reg, uint16_t clearbits, uint16_t setbits)
328 {
329  uint16_t val = read_reg16(reg);
330  val &= ~clearbits;
331  val |= setbits;
332  write_reg16(reg, val);
333 }
334 
335 uint16_t
337 {
338  uint16_t cmd[1];
339 
340  cmd[0] = ((reg | DIR_READ) << 8) & 0xff00;
341 
342  transferhword(cmd, nullptr, 1);
343  usleep(T_STALL);
344  transferhword(nullptr, cmd, 1);
345  usleep(T_STALL);
346 
347  return cmd[0];
348 }
349 
350 void
351 ADIS16448::write_reg16(unsigned reg, uint16_t value)
352 {
353  uint16_t cmd[2];
354 
355  cmd[0] = ((reg | DIR_WRITE) << 8) | (0x00ff & value);
356  cmd[1] = (((reg + 0x1) | DIR_WRITE) << 8) | ((0xff00 & value) >> 8);
357 
358  transferhword(cmd, nullptr, 1);
359  usleep(T_STALL);
360  transferhword(cmd + 1, nullptr, 1);
361  usleep(T_STALL);
362 }
363 
364 void
366 {
367  // Make sure we are stopped first.
368  stop();
369 
370  // Start polling at the specified interval
371  ScheduleOnInterval((1_s / _sample_rate), 10000);
372 }
373 
374 void
376 {
377  ScheduleClear();
378 }
379 
380 // computes the CCITT CRC16 on the data received from a burst read
381 static uint16_t ComputeCRC16(uint16_t burstData[13])
382 {
383  uint16_t crc = 0xFFFF; // Holds the CRC value
384 
385  unsigned int data; // Holds the lower/Upper byte for CRC computation
386  static constexpr unsigned int POLY = 0x1021; // Divisor used during CRC computation
387 
388  // Compute CRC on burst data starting from XGYRO_OUT and ending with TEMP_OUT.
389  // Start with the lower byte and then the upper byte of each word.
390  // i.e. Compute XGYRO_OUT_LSB CRC first and then compute XGYRO_OUT_MSB CRC.
391  for (int i = 1; i < 12; i++) {
392  unsigned int upperByte = (burstData[i] >> 8) & 0xFF;
393  unsigned int lowerByte = (burstData[i] & 0xFF);
394  data = lowerByte; // Compute lower byte CRC first
395 
396  for (int ii = 0; ii < 8; ii++, data >>= 1) {
397  if ((crc & 0x0001) ^ (data & 0x0001)) {
398  crc = (crc >> 1) ^ POLY;
399 
400  } else {
401  crc >>= 1;
402  }
403  }
404 
405  data = upperByte; // Compute upper byte of CRC
406 
407  for (int ii = 0; ii < 8; ii++, data >>= 1) {
408  if ((crc & 0x0001) ^ (data & 0x0001)) {
409  crc = (crc >> 1) ^ POLY;
410 
411  } else {
412  crc >>= 1;
413  }
414  }
415  }
416 
417  crc = ~crc; // Compute complement of CRC
418  data = crc;
419  crc = (crc << 8) | (data >> 8 & 0xFF); // Perform byte swap prior to returning CRC
420 
421  return crc;
422 }
423 
424 /**
425  * convert 12 bit integer format to int16.
426  */
427 static int16_t
428 convert12BitToINT16(uint16_t word)
429 {
430  int16_t outputbuffer = 0;
431 
432  if ((word >> 11) & 0x1) {
433  outputbuffer = (word & 0xfff) | 0xf000;
434 
435  } else {
436  outputbuffer = (word & 0x0fff);
437  }
438 
439  return (outputbuffer);
440 }
441 
442 int
444 {
445  // Start measuring.
447 
448  // Fetch the full set of measurements from the ADIS16448 in one pass (burst read).
449 #pragma pack(push, 1) // Ensure proper memory alignment.
450  struct Report {
451  uint16_t cmd;
452 
453  uint16_t DIAG_STAT;
454 
455  int16_t XGYRO_OUT;
456  int16_t YGYRO_OUT;
457  int16_t ZGYRO_OUT;
458 
459  int16_t XACCL_OUT;
460  int16_t YACCL_OUT;
461  int16_t ZACCL_OUT;
462 
463  int16_t XMAGN_OUT;
464  int16_t YMAGN_OUT;
465  int16_t ZMAGN_OUT;
466 
467  uint16_t BARO_OUT;
468 
469  uint16_t TEMP_OUT;
470 
471  uint16_t CRC16;
472  } report{};
473 #pragma pack(pop)
474 
475  report.cmd = ((ADIS16448_GLOB_CMD | DIR_READ) << 8) & 0xff00;
476 
477  const hrt_abstime timestamp_sample = hrt_absolute_time();
478 
480 
481  if (OK != transferhword((uint16_t *)&report, ((uint16_t *)&report), sizeof(report) / sizeof(int16_t))) {
484 
486 
487  return -EIO;
488  }
489 
491 
492  // checksum
493  if (report.CRC16 != ComputeCRC16((uint16_t *)&report.DIAG_STAT)) {
496  return -EIO;
497  }
498 
499  // error count
500  const uint64_t error_count = perf_event_count(_perf_bad_transfer) + perf_event_count(_perf_crc_bad);
501 
502  // temperature
503  const float temperature = (convert12BitToINT16(report.TEMP_OUT) * 0.07386f) + 31.0f; // 0.07386°C/LSB, 31°C = 0x000
504 
505  _px4_accel.set_error_count(error_count);
506  _px4_accel.set_temperature(temperature);
507  _px4_accel.update(timestamp_sample, report.XACCL_OUT, report.YACCL_OUT, report.ZACCL_OUT);
508 
509  _px4_gyro.set_error_count(error_count);
510  _px4_gyro.set_temperature(temperature);
511  _px4_gyro.update(timestamp_sample, report.XGYRO_OUT, report.YGYRO_OUT, report.ZGYRO_OUT);
512 
513  // DIAG_STAT bit 7: New data, xMAGN_OUT/BARO_OUT
514  const bool baro_mag_update = (report.DIAG_STAT & (1 << 7));
515 
516  if (baro_mag_update) {
517  _px4_mag.set_error_count(error_count);
518  _px4_mag.set_temperature(temperature);
519  _px4_mag.update(timestamp_sample, report.XMAGN_OUT, report.YMAGN_OUT, report.ZMAGN_OUT);
520 
521  _px4_baro.set_error_count(error_count);
522  _px4_baro.set_temperature(temperature);
523  _px4_baro.update(timestamp_sample, report.BARO_OUT * ADIS16448_BARO_SENSITIVITY);
524  }
525 
526  // Stop measuring.
528 
529  return OK;
530 }
531 
532 void
534 {
535  // Make another measurement.
536  measure();
537 }
bool self_test()
Definition: ADIS16448.cpp:136
void print_status()
#define ADIS16448_MSC_CTRL
Definition: ADIS16448.h:61
#define BITS_SMPL_PRD_8_TAP_CFG
Definition: ADIS16448.h:74
void print_info()
Diagnostics - print some basic information about the driver and sensor.
Definition: ADIS16448.cpp:313
#define BITS_SMPL_PRD_4_TAP_CFG
Definition: ADIS16448.h:73
void set_temperature(float temperature)
#define BITS_GYRO_DYN_RANGE_500_CFG
Definition: ADIS16448.h:78
#define ADIS16448_PRODUCT_ID
Definition: ADIS16448.h:66
static struct vehicle_status_s status
Definition: Commander.cpp:138
void set_sample_rate(unsigned rate)
#define ADIS16448_DIAG_STAT
Definition: ADIS16448.h:64
#define ADIS16448_Product
Definition: ADIS16448.h:69
#define ADIS16448_GPIO_CTRL
Definition: ADIS16448.h:60
void print_status()
static constexpr float ADIS16448_MAG_SENSITIVITY
Definition: ADIS16448.h:95
static constexpr float ADIS16448_BARO_SENSITIVITY
Definition: ADIS16448.h:94
void set_device_type(uint8_t devtype)
void set_error_count(uint64_t error_count)
void set_error_count(uint64_t error_count)
PX4Accelerometer _px4_accel
Definition: ADIS16448.h:204
#define ADIS16448_SENS_AVG
Definition: ADIS16448.h:63
void update(hrt_abstime timestamp, float x, float y, float z)
#define ADIS16448_GLOB_CMD
Definition: ADIS16448.h:65
void Run()
Static trampoline from the hrt_call context; because we don&#39;t have a generic hrt wrapper yet...
Definition: ADIS16448.cpp:533
#define DRV_GYR_DEVTYPE_ADIS16448
Definition: drv_sensor.h:108
#define DRV_ACC_DEVTYPE_ADIS16448
Definition: drv_sensor.h:106
uint16_t read_reg16(unsigned reg)
Read a register from the ADIS16448.
Definition: ADIS16448.cpp:336
perf_counter_t _perf_crc_bad
Definition: ADIS16448.h:216
bool set_dlpf_filter(uint16_t frequency_hz)
Set low pass filter frequency.
Definition: ADIS16448.cpp:268
Namespace encapsulating all device framework classes, functions and data.
Definition: CDev.cpp:47
#define BITS_GYRO_DYN_RANGE_250_CFG
Definition: ADIS16448.h:79
void set_device_type(uint8_t devtype)
void set_error_count(uint64_t error_count)
bool set_sample_rate(uint16_t desired_sample_rate_hz)
Set sample rate (approximate) - 1kHz to 5Hz.
Definition: ADIS16448.cpp:233
void set_external(bool external)
static uint16_t ComputeCRC16(uint16_t burstData[13])
Definition: ADIS16448.cpp:381
#define DIR_READ
Definition: bmp388_spi.cpp:46
bool set_gyro_dyn_range(uint16_t desired_gyro_dyn_range)
Set the gyroscope dynamic range.
Definition: ADIS16448.cpp:284
static constexpr float ADIS16448_GYRO_INITIAL_SENSITIVITY
Definition: ADIS16448.h:93
virtual int probe()
Definition: ADIS16448.cpp:195
void update(hrt_abstime timestamp, float x, float y, float z)
#define BITS_SMPL_PRD_16_TAP_CFG
Definition: ADIS16448.h:75
void perf_count(perf_counter_t handle)
Count a performance event.
static int16_t convert12BitToINT16(uint16_t word)
convert 12 bit integer format to int16.
Definition: ADIS16448.cpp:428
void perf_free(perf_counter_t handle)
Free a counter.
void set_temperature(float temperature)
void init()
Activates/configures the hardware registers.
void set_temperature(float temperature)
void set_sample_rate(unsigned rate)
void stop()
Stop automatic measurement.
Definition: ADIS16448.cpp:375
PX4Barometer _px4_baro
Definition: ADIS16448.h:205
void update(hrt_abstime timestamp, float pressure)
void update(hrt_abstime timestamp, int16_t x, int16_t y, int16_t z)
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
uint8_t * data
Definition: dataman.cpp:149
static constexpr float ADIS16448_ACCEL_SENSITIVITY
Definition: ADIS16448.h:92
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
virtual int init()
Definition: ADIS16448.cpp:73
PX4Magnetometer _px4_mag
Definition: ADIS16448.h:207
void set_error_count(uint64_t error_count)
bool reset()
Resets the chip and measurements ranges.
Definition: ADIS16448.cpp:97
void perf_end(perf_counter_t handle)
End a performance event.
#define ADIS16448_SMPL_PRD
Definition: ADIS16448.h:62
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
void write_reg16(unsigned reg, uint16_t value)
Write a register in the ADIS16448.
Definition: ADIS16448.cpp:351
static constexpr float _sample_rate
Definition: ADIS16448.h:211
void set_scale(float scale)
void set_scale(float scale)
void start()
Start automatic measurement.
Definition: ADIS16448.cpp:365
#define DIR_WRITE
Definition: bmp388_spi.cpp:47
ADIS16448(int bus, uint32_t device, enum Rotation rotation)
Definition: ADIS16448.cpp:40
#define DRV_MAG_DEVTYPE_ADIS16448
Definition: drv_sensor.h:107
void set_temperature(float temperature)
perf_counter_t _perf_read
Definition: ADIS16448.h:213
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
uint64_t perf_event_count(perf_counter_t handle)
Return current event_count.
#define BITS_GYRO_DYN_RANGE_1000_CFG
Definition: ADIS16448.h:77
Definition: bst.cpp:62
perf_counter_t _perf_bad_transfer
Definition: ADIS16448.h:215
perf_counter_t _perf_transfer
Definition: ADIS16448.h:214
#define OK
Definition: uavcan_main.cpp:71
#define M_PI_F
Definition: ashtech.cpp:44
virtual ~ADIS16448()
Definition: ADIS16448.cpp:60
void set_scale(float scale)
void set_device_type(uint8_t devtype)
PX4Gyroscope _px4_gyro
Definition: ADIS16448.h:206
#define ADIS16334_SERIAL_NUMBER
Definition: ADIS16448.h:67
#define BITS_SMPL_PRD_2_TAP_CFG
Definition: ADIS16448.h:72
#define BITS_SMPL_PRD_NO_TAP_CFG
Definition: ADIS16448.h:71
void modify_reg16(unsigned reg, uint16_t clearbits, uint16_t setbits)
Modify a register in the ADIS16448 Bits are cleared before bits are set.
Definition: ADIS16448.cpp:327
void perf_begin(perf_counter_t handle)
Begin a performance event.
#define T_STALL
Definition: ADIS16448.h:90
int measure()
Fetch measurements from the sensor and update the report buffers.
Definition: ADIS16448.cpp:443
#define DEVICE_DEBUG(FMT,...)
Definition: Device.hpp:52
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
uint16_t _product_ID
Definition: ADIS16448.h:209
void set_device_type(uint8_t devtype)