PX4 Firmware
PX4 Autopilot Software http://px4.io
rm3100.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2018 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 rm3100.cpp
36  *
37  * Driver for the RM3100 magnetometer connected via I2C or SPI.
38  *
39  * Based on the lis3mdl driver.
40  */
41 
42 #include "rm3100.h"
43 
44 RM3100::RM3100(device::Device *interface, const char *path, enum Rotation rotation) :
45  CDev("RM3100", path),
46  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())),
47  _interface(interface),
48  _reports(nullptr),
49  _scale{},
50  _last_report{},
51  _mag_topic(nullptr),
52  _comms_errors(perf_alloc(PC_COUNT, "rm3100_comms_errors")),
53  _conf_errors(perf_alloc(PC_COUNT, "rm3100_conf_errors")),
54  _range_errors(perf_alloc(PC_COUNT, "rm3100_range_errors")),
55  _sample_perf(perf_alloc(PC_ELAPSED, "rm3100_read")),
56  _calibrated(false),
57  _continuous_mode_set(false),
58  _mode(SINGLE),
59  _rotation(rotation),
61  _class_instance(-1),
65 {
66  // set the device type from the interface
67  _device_id.devid_s.bus_type = _interface->get_device_bus_type();
68  _device_id.devid_s.bus = _interface->get_device_bus();
69  _device_id.devid_s.address = _interface->get_device_address();
70  _device_id.devid_s.devtype = DRV_MAG_DEVTYPE_RM3100;
71 
72  // default scaling
73  _scale.x_offset = 0;
74  _scale.x_scale = 1.0f;
75  _scale.y_offset = 0;
76  _scale.y_scale = 1.0f;
77  _scale.z_offset = 0;
78  _scale.z_scale = 1.0f;
79 }
80 
82 {
83  /* make sure we are truly inactive */
84  stop();
85 
86  if (_reports != nullptr) {
87  delete _reports;
88  }
89 
90  if (_class_instance != -1) {
92  }
93 
94  // free perf counters
99 }
100 
101 int
103 {
104  /* Stop current measurements */
105  stop();
106 
107  /* Chances are that a poll event was triggered, so wait for conversion and read registers in order to clear DRDY bit */
109  collect();
110 
111  /* Fail if calibration is not good */
112  int ret = 0;
113  uint8_t cmd = 0;
114 
115  /* Configure mag into self test mode */
116  cmd = BIST_SELFTEST;
117  ret = _interface->write(ADDR_BIST, &cmd, 1);
118 
119  if (ret != PX4_OK) {
120  return ret;
121  }
122 
123  /* Now we need to write to POLL to launch self test */
124  cmd = POLL_XYZ;
125  ret = _interface->write(ADDR_POLL, &cmd, 1);
126 
127  if (ret != PX4_OK) {
128  return ret;
129  }
130 
131  /* Now wait for status register */
133 
134  if (check_measurement() != PX4_OK) {
135  return -1;;
136  }
137 
138  /* Now check BIST register to see whether self test is ok or not*/
139  ret = _interface->read(ADDR_BIST, &cmd, 1);
140 
141  if (ret != PX4_OK) {
142  return ret;
143  }
144 
145  ret = !((cmd & BIST_XYZ_OK) == BIST_XYZ_OK);
146 
147  /* Restart measurement state machine */
148  start();
149 
150  return ret;
151 }
152 
153 int
155 {
156  uint8_t status = 0;
157  int ret = -1;
158 
159  ret = _interface->read(ADDR_STATUS, &status, 1);
160 
161  if (ret != 0) {
162  return ret;
163  }
164 
165  return !((status & STATUS_DRDY) == STATUS_DRDY) ;
166 }
167 
168 int
170 {
171  /* Check whether a measurement is available or not, otherwise return immediately */
172  if (check_measurement() != 0) {
173  DEVICE_DEBUG("No measurement available");
174  return 0;
175  }
176 
177 #pragma pack(push, 1)
178  struct {
179  uint8_t x[3];
180  uint8_t y[3];
181  uint8_t z[3];
182  } rm_report;
183 #pragma pack(pop)
184 
185  int ret = 0;
186 
187  int32_t xraw;
188  int32_t yraw;
189  int32_t zraw;
190 
191  float xraw_f;
192  float yraw_f;
193  float zraw_f;
194 
195  struct mag_report new_mag_report;
196  bool sensor_is_onboard = false;
197 
199 
200  new_mag_report.timestamp = hrt_absolute_time();
201  new_mag_report.error_count = perf_event_count(_comms_errors);
202  new_mag_report.scaling = _range_scale;
203  new_mag_report.device_id = _device_id.devid;
204 
205  ret = _interface->read(ADDR_MX, (uint8_t *)&rm_report, sizeof(rm_report));
206 
207  if (ret != OK) {
209  PX4_WARN("Register read error.");
210  return ret;
211  }
212 
213  /* Rearrange mag data */
214  xraw = ((rm_report.x[0] << 16) | (rm_report.x[1] << 8) | rm_report.x[2]);
215  yraw = ((rm_report.y[0] << 16) | (rm_report.y[1] << 8) | rm_report.y[2]);
216  zraw = ((rm_report.z[0] << 16) | (rm_report.z[1] << 8) | rm_report.z[2]);
217 
218  /* Convert 24 bit signed values to 32 bit signed values */
219  convert_signed(&xraw);
220  convert_signed(&yraw);
221  convert_signed(&zraw);
222 
223  /* There is no temperature sensor */
224  new_mag_report.temperature = 0.0f;
225 
226  // XXX revisit for SPI part, might require a bus type IOCTL
227  unsigned dummy = 0;
228  sensor_is_onboard = !_interface->ioctl(MAGIOCGEXTERNAL, dummy);
229  new_mag_report.is_external = !sensor_is_onboard;
230 
231  /**
232  * RAW outputs
233  * As we only have 16 bits to store raw data, the following values are not correct
234  */
235  new_mag_report.x_raw = (int16_t)(xraw >> 8);
236  new_mag_report.y_raw = (int16_t)(yraw >> 8);
237  new_mag_report.z_raw = (int16_t)(zraw >> 8);
238 
239  xraw_f = xraw;
240  yraw_f = yraw;
241  zraw_f = zraw;
242 
243  /* apply user specified rotation */
244  rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);
245 
246  new_mag_report.x = ((xraw_f * _range_scale) - _scale.x_offset) * _scale.x_scale;
247  new_mag_report.y = ((yraw_f * _range_scale) - _scale.y_offset) * _scale.y_scale;
248  new_mag_report.z = ((zraw_f * _range_scale) - _scale.z_offset) * _scale.z_scale;
249 
250  if (!(_pub_blocked)) {
251 
252  if (_mag_topic != nullptr) {
253  /* publish it */
254  orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_mag_report);
255 
256  } else {
257  _mag_topic = orb_advertise_multi(ORB_ID(sensor_mag), &new_mag_report,
258  &_orb_class_instance, (sensor_is_onboard) ? ORB_PRIO_HIGH : ORB_PRIO_MAX);
259 
260  if (_mag_topic == nullptr) {
261  DEVICE_DEBUG("ADVERT FAIL");
262  }
263  }
264  }
265 
266  _last_report = new_mag_report;
267 
268  /* post a report to the ring */
269  _reports->force(&new_mag_report);
270 
271  /* notify anyone waiting for data */
272  poll_notify(POLLIN);
273 
274  ret = OK;
275 
277  return ret;
278 }
279 
280 void
282 {
283  /* Sensor returns values as 24 bit signed values, so we need to manually convert to 32 bit signed values */
284  if ((*n & (1 << 23)) == (1 << 23)) {
285  *n |= 0xFF000000;
286  }
287 }
288 
289 void
291 {
292  /* _measure_interval == 0 is used as _task_should_exit */
293  if (_measure_interval == 0) {
294  return;
295  }
296 
297  /* Collect last measurement at the start of every cycle */
298  if (collect() != OK) {
299  DEVICE_DEBUG("collection error");
300  /* restart the measurement state machine */
301  start();
302  return;
303  }
304 
305 
306  if (measure() != OK) {
307  DEVICE_DEBUG("measure error");
308  }
309 
310  if (_measure_interval > 0) {
311  /* schedule a fresh cycle call when the measurement is done */
312  ScheduleDelayed(_measure_interval);
313  }
314 }
315 
316 int
318 {
319  int ret = PX4_ERROR;
320 
321  ret = CDev::init();
322 
323  if (ret != OK) {
324  DEVICE_DEBUG("CDev init failed");
325  return ret;
326  }
327 
328  /* allocate basic report buffers */
329  _reports = new ringbuffer::RingBuffer(2, sizeof(mag_report));
330 
331  if (_reports == nullptr) {
332  return PX4_ERROR;
333  }
334 
335  /* reset the device configuration */
336  reset();
337 
339 
340  ret = self_test();
341 
342  if (ret != PX4_OK) {
343  PX4_ERR("self test failed");
344  }
345 
346  return ret;
347 }
348 
349 int
350 RM3100::ioctl(struct file *file_pointer, int cmd, unsigned long arg)
351 {
352  unsigned dummy = 0;
353 
354  switch (cmd) {
355  case SENSORIOCSPOLLRATE: {
356  switch (arg) {
357 
358  /* zero would be bad */
359  case 0:
360  return -EINVAL;
361 
363  /* do we need to start internal polling? */
364  bool not_started = (_measure_interval == 0);
365 
366  /* set interval for next measurement to minimum legal value */
368 
369  /* if we need to start the poll state machine, do it */
370  if (not_started) {
371  start();
372  }
373 
374  return PX4_OK;
375  }
376 
377  /* Uses arg (hz) for a custom poll rate */
378  default: {
379  /* do we need to start internal polling? */
380  bool not_started = (_measure_interval == 0);
381 
382  /* convert hz to tick interval via microseconds */
383  unsigned interval = (1000000 / arg);
384 
385  /* check against maximum rate */
386  if (interval < RM3100_CONVERSION_INTERVAL) {
387  return -EINVAL;
388  }
389 
390  /* update interval for next measurement */
391  _measure_interval = interval;
392 
393  /* if we need to start the poll state machine, do it */
394  if (not_started) {
395  start();
396  }
397 
398  return PX4_OK;
399  }
400  }
401  }
402 
403  case SENSORIOCRESET:
404  return reset();
405 
406  case MAGIOCSRANGE:
407  /* field measurement range cannot be configured for this sensor (8 Gauss) */
408  return OK;
409 
410  case MAGIOCSSCALE:
411  /* set new scale factors */
412  memcpy(&_scale, (struct mag_calibration_s *)arg, sizeof(_scale));
413  return 0;
414 
415  case MAGIOCGSCALE:
416  /* copy out scale factors */
417  memcpy((struct mag_calibration_s *)arg, &_scale, sizeof(_scale));
418  return 0;
419 
420 
421  case MAGIOCCALIBRATE:
422  /* This is left for compatibility with the IOCTL call in mag calibration */
423  return OK;
424 
425  case MAGIOCGEXTERNAL:
426  DEVICE_DEBUG("MAGIOCGEXTERNAL in main driver");
427  return _interface->ioctl(cmd, dummy);
428 
429  case DEVIOCGDEVICEID:
430  return _interface->ioctl(cmd, dummy);
431 
432  default:
433  /* give it to the superclass */
434  return CDev::ioctl(file_pointer, cmd, arg);
435  }
436 }
437 
438 int
440 {
441  int ret = 0;
442  uint8_t cmd = 0;
443 
444  /* Send the command to begin a measurement. */
445  if ((_mode == CONTINUOUS) && !_continuous_mode_set) {
446  cmd = (CMM_DEFAULT | CONTINUOUS_MODE);
447  ret = _interface->write(ADDR_CMM, &cmd, 1);
448  _continuous_mode_set = true;
449 
450  } else if (_mode == SINGLE) {
451  if (_continuous_mode_set) {
452  /* This is needed for polling mode */
453  cmd = (CMM_DEFAULT | POLLING_MODE);
454  ret = _interface->write(ADDR_CMM, &cmd, 1);
455 
456  if (ret != OK) {
458  return ret;
459  }
460 
461  _continuous_mode_set = false;
462  }
463 
464  cmd = POLL_XYZ;
465  ret = _interface->write(ADDR_POLL, &cmd, 1);
466  }
467 
468 
469  if (ret != OK) {
471  }
472 
473  return ret;
474 }
475 
476 void
478 {
481  PX4_INFO("poll interval: %u", _measure_interval);
482  print_message(_last_report);
483  _reports->print_info("report queue");
484 }
485 
486 int
488 {
489  int ret = 0;
490 
492 
493  if (ret != OK) {
494  return PX4_ERROR;
495  }
496 
497  return PX4_OK;
498 }
499 
500 int
501 RM3100::read(struct file *file_pointer, char *buffer, size_t buffer_len)
502 {
503  unsigned count = buffer_len / sizeof(struct mag_report);
504  struct mag_report *mag_buf = reinterpret_cast<struct mag_report *>(buffer);
505  int ret = 0;
506 
507  /* buffer must be large enough */
508  if (count < 1) {
509  return -ENOSPC;
510  }
511 
512  /* if automatic measurement is enabled */
513  if (_measure_interval > 0) {
514  /*
515  * While there is space in the caller's buffer, and reports, copy them.
516  * Note that we may be pre-empted by the workq thread while we are doing this;
517  * we are careful to avoid racing with them.
518  */
519  while (count--) {
520  if (_reports->get(mag_buf)) {
521  ret += sizeof(struct mag_report);
522  mag_buf++;
523  }
524  }
525 
526  /* if there was no data, warn the caller */
527  return ret ? ret : -EAGAIN;
528  }
529 
530  /* manual measurement - run one conversion */
531  /* XXX really it'd be nice to lock against other readers here */
532  do {
533  _reports->flush();
534 
535  /* trigger a measurement */
536  if (measure() != OK) {
537  ret = -EIO;
538  break;
539  }
540 
541  /* wait for it to complete */
543 
544  /* run the collection phase */
545  if (collect() != OK) {
546  ret = -EIO;
547  break;
548  }
549 
550  if (_reports->get(mag_buf)) {
551  ret = sizeof(struct mag_report);
552  }
553  } while (0);
554 
555  return ret;
556 }
557 
558 int
560 {
561  uint8_t cmd[2] = {0, 0};
562 
563  cmd[0] = CCX_DEFAULT_MSB;
564  cmd[1] = CCX_DEFAULT_LSB;
565  _interface->write(ADDR_CCX, cmd, 2);
566 
567  cmd[0] = CCY_DEFAULT_MSB;
568  cmd[1] = CCY_DEFAULT_LSB;
569  _interface->write(ADDR_CCY, cmd, 2);
570 
571  cmd[0] = CCZ_DEFAULT_MSB;
572  cmd[1] = CCZ_DEFAULT_LSB;
573  _interface->write(ADDR_CCZ, cmd, 2);
574 
575  cmd[0] = CMM_DEFAULT;
576  _interface->write(ADDR_CMM, cmd, 1);
577 
578  cmd[0] = TMRC_DEFAULT;
579  _interface->write(ADDR_TMRC, cmd, 1);
580 
581  cmd[0] = BIST_DEFAULT;
582  _interface->write(ADDR_BIST, cmd, 1);
583 
584  return PX4_OK;
585 }
586 
587 void
589 {
590  /* reset the report ring and state machine */
591  _reports->flush();
592 
595 
596  /* schedule a cycle to start things */
597  ScheduleNow();
598 }
599 
600 void
602 {
603  if (_measure_interval > 0) {
604  /* ensure no new items are queued while we cancel this one */
605  _measure_interval = 0;
606  ScheduleClear();
607  }
608 }
#define RM3100_CONVERSION_INTERVAL
RM3100 internal constants and data structures.
Definition: rm3100.h:62
#define MAGIOCGSCALE
copy the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:76
#define MAGIOCGEXTERNAL
determine if mag is external or onboard
Definition: drv_mag.h:88
#define BIST_SELFTEST
Definition: rm3100.h:90
perf_counter_t _conf_errors
Definition: rm3100.h:160
int collect()
Collect the result of the most recent measurement.
Definition: rm3100.cpp:169
virtual int read(struct file *file_pointer, char *buffer, size_t buffer_len)
Definition: rm3100.cpp:501
static struct vehicle_status_s status
Definition: Commander.cpp:138
measure the time elapsed performing an event
Definition: perf_counter.h:56
#define ADDR_TMRC
Definition: rm3100.h:71
enum Rotation _rotation
Definition: rm3100.h:169
#define CONTINUOUS_MODE
Definition: rm3100.h:87
int self_test()
Run sensor self-test.
Definition: rm3100.cpp:102
perf_counter_t _sample_perf
Definition: rm3100.h:162
bool _calibrated
the calibration is valid
Definition: rm3100.h:165
virtual int register_class_devname(const char *class_devname)
Register a class device name, automatically adding device class instance suffix if need be...
Definition: CDev.cpp:78
#define ADDR_CCX
Definition: rm3100.h:68
#define SENSOR_POLLRATE_DEFAULT
poll at driver normal rate
Definition: drv_sensor.h:136
__EXPORT void rotate_3f(enum Rotation rot, float &x, float &y, float &z)
rotate a 3 element float vector in-place
Definition: rotation.cpp:63
#define CMM_DEFAULT
Definition: rm3100.h:86
void stop()
Stop the automatic measurement state machine.
Definition: rm3100.cpp:601
#define BIST_XYZ_OK
Definition: rm3100.h:92
#define TMRC_DEFAULT
Definition: rm3100.h:89
enum OPERATING_MODE _mode
Definition: rm3100.h:168
perf_counter_t _comms_errors
Definition: rm3100.h:159
mag scaling factors; Vout = (Vin * Vscale) + Voffset
Definition: drv_mag.h:56
bool _continuous_mode_set
Definition: rm3100.h:166
virtual int ioctl(struct file *file_pointer, int cmd, unsigned long arg)
Definition: rm3100.cpp:350
struct mag_calibration_s _scale
Definition: rm3100.h:153
count the number of times an event occurs
Definition: perf_counter.h:55
#define UTESLA_TO_GAUSS
Definition: rm3100.h:63
#define ADDR_BIST
Definition: rm3100.h:75
int reset()
Resets the device.
Definition: rm3100.cpp:487
#define MAGIOCSRANGE
set the measurement range to handle (at least) arg Gauss
Definition: drv_mag.h:79
virtual void poll_notify(pollevent_t events)
Report new poll events.
Definition: CDev.cpp:330
virtual ~RM3100()
Definition: rm3100.cpp:81
float x_offset
Definition: drv_mag.h:57
#define SENSORIOCSPOLLRATE
Set the driver polling rate to (arg) Hz, or one of the SENSOR_POLLRATE constants. ...
Definition: drv_sensor.h:134
#define CCX_DEFAULT_MSB
Definition: rm3100.h:80
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
int set_default_register_values()
Configures the device with default register values.
Definition: rm3100.cpp:559
device identifier information
Definition: Device.hpp:240
void perf_count(perf_counter_t handle)
Count a performance event.
#define CCY_DEFAULT_LSB
Definition: rm3100.h:83
#define MAGIOCSSCALE
set the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:73
void perf_free(perf_counter_t handle)
Free a counter.
#define MAG_BASE_DEVICE_PATH
Definition: drv_mag.h:47
void init()
Activates/configures the hardware registers.
#define MAGIOCCALIBRATE
perform self-calibration, update scale factors to canonical units
Definition: drv_mag.h:82
virtual int init()
Definition: rm3100.cpp:317
virtual int unregister_class_devname(const char *class_devname, unsigned class_instance)
Register a class device name, automatically adding device class instance suffix if need be...
Definition: CDev.cpp:109
#define perf_alloc(a, b)
Definition: px4io.h:59
#define DRV_MAG_DEVTYPE_RM3100
Definition: drv_sensor.h:61
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
orb_advert_t _mag_topic
Definition: rm3100.h:157
void convert_signed(int32_t *n)
Converts int24_t stored in 32-bit container to int32_t.
Definition: rm3100.cpp:281
#define ADDR_CCZ
Definition: rm3100.h:70
float y_offset
Definition: drv_mag.h:59
RM3100(device::Device *interface, const char *path, enum Rotation rotation)
Definition: rm3100.cpp:44
#define STATUS_DRDY
Definition: rm3100.h:93
void perf_end(perf_counter_t handle)
End a performance event.
void print_info()
Diagnostics - print some basic information about the driver.
Definition: rm3100.cpp:477
unsigned int _measure_interval
Definition: rm3100.h:171
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
float z_offset
Definition: drv_mag.h:61
int check_measurement()
Check whether new data is available or not.
Definition: rm3100.cpp:154
used for info()
Definition: rm3100.h:155
perf_counter_t _range_errors
Definition: rm3100.h:161
ringbuffer::RingBuffer * _reports
Definition: rm3100.h:151
int _orb_class_instance
Definition: rm3100.h:174
Device * _interface
Definition: rm3100.h:147
void Run() override
Performs a poll cycle; collect from the previous measurement and start a new one. ...
Definition: rm3100.cpp:290
#define POLLING_MODE
Definition: rm3100.h:88
int measure()
Issue a measurement command.
Definition: rm3100.cpp:439
#define ADDR_CCY
Definition: rm3100.h:69
uint8_t _check_state_cnt
Definition: rm3100.h:178
struct @83::@85::@87 file
int _class_instance
Definition: rm3100.h:173
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
#define SENSORIOCRESET
Reset the sensor to its default configuration.
Definition: drv_sensor.h:141
uint64_t perf_event_count(perf_counter_t handle)
Return current event_count.
#define CCX_DEFAULT_LSB
Definition: rm3100.h:81
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
#define CCZ_DEFAULT_LSB
Definition: rm3100.h:85
Definition: bst.cpp:62
Shared defines for the RM3100 driver.
void start()
Initialises the automatic measurement state machine and start it.
Definition: rm3100.cpp:588
#define BIST_DEFAULT
Definition: rm3100.h:91
#define ADDR_CMM
Definition: rm3100.h:67
#define OK
Definition: uavcan_main.cpp:71
#define RM3100_SENSITIVITY
Definition: rm3100.h:64
#define ADDR_STATUS
Definition: HMC5883.hpp:89
bool _pub_blocked
true if publishing should be blocked
Definition: CDev.hpp:91
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
#define ADDR_POLL
Definition: rm3100.h:66
#define ADDR_MX
Definition: rm3100.h:72
void perf_begin(perf_counter_t handle)
Begin a performance event.
#define CCY_DEFAULT_MSB
Definition: rm3100.h:82
#define DEVICE_DEBUG(FMT,...)
Definition: Device.hpp:52
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
float _range_scale
Definition: rm3100.h:176
#define POLL_XYZ
Definition: rm3100.h:94
#define CCZ_DEFAULT_MSB
Definition: rm3100.h:84
#define mag_report
Definition: drv_mag.h:53