PX4 Firmware
PX4 Autopilot Software http://px4.io
ist8310.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2016 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 ist8310.cpp
36  *
37  * Driver for the IST8310 magnetometer connected via I2C.
38  *
39  * @author David Sidrane
40  * @author Maelok Dong
41  */
42 
43 #include <px4_platform_common/px4_config.h>
44 #include <px4_platform_common/defines.h>
45 #include <px4_platform_common/getopt.h>
46 
47 #include <sys/types.h>
48 #include <stdint.h>
49 #include <stdlib.h>
50 #include <stdbool.h>
51 #include <semaphore.h>
52 #include <string.h>
53 #include <fcntl.h>
54 #include <poll.h>
55 #include <errno.h>
56 #include <stdio.h>
57 #include <math.h>
58 #include <unistd.h>
59 
60 #include <nuttx/arch.h>
61 #include <nuttx/clock.h>
62 
63 #include <board_config.h>
64 
65 #include <perf/perf_counter.h>
66 #include <systemlib/err.h>
67 
68 #include <drivers/device/i2c.h>
69 #include <drivers/drv_mag.h>
70 #include <drivers/drv_hrt.h>
72 #include <drivers/drv_device.h>
73 
74 #include <uORB/uORB.h>
75 
76 #include <float.h>
78 
79 #include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
80 
81 /*
82  * IST8310 internal constants and data structures.
83  */
84 
85 /* Max measurement rate is 160Hz, however with 160 it will be set to 166 Hz, therefore workaround using 150
86  * The datasheet gives 200Hz maximum measurement rate, but it's not true according to tech support from iSentek*/
87 #define IST8310_CONVERSION_INTERVAL (1000000 / 100) /* microseconds */
88 
89 #define IST8310_BUS_I2C_ADDR 0xE
90 #define IST8310_DEFAULT_BUS_SPEED 400000
91 
92 /*
93  * FSR:
94  * x, y: +- 1600 µT
95  * z: +- 2500 µT
96  *
97  * Resolution according to datasheet is 0.3µT/LSB
98  */
99 #define IST8310_RESOLUTION 0.3
100 
101 static const int16_t IST8310_MAX_VAL_XY = (1600 / IST8310_RESOLUTION) + 1;
102 static const int16_t IST8310_MIN_VAL_XY = -IST8310_MAX_VAL_XY;
103 static const int16_t IST8310_MAX_VAL_Z = (2500 / IST8310_RESOLUTION) + 1;
104 static const int16_t IST8310_MIN_VAL_Z = -IST8310_MAX_VAL_Z;
105 
106 /* Hardware definitions */
107 
108 #define ADDR_WAI 0 /* WAI means 'Who Am I'*/
109 # define WAI_EXPECTED_VALUE 0x10
110 
111 #define ADDR_STAT1 0x02
112 # define STAT1_DRDY_SHFITS 0x0
113 # define STAT1_DRDY (1 << STAT1_DRDY_SHFITS)
114 # define STAT1_DRO_SHFITS 0x1
115 # define STAT1_DRO (1 << STAT1_DRO_SHFITS)
116 
117 #define ADDR_DATA_OUT_X_LSB 0x03
118 #define ADDR_DATA_OUT_X_MSB 0x04
119 #define ADDR_DATA_OUT_Y_LSB 0x05
120 #define ADDR_DATA_OUT_Y_MSB 0x06
121 #define ADDR_DATA_OUT_Z_LSB 0x07
122 #define ADDR_DATA_OUT_Z_MSB 0x08
123 
124 #define ADDR_STAT2 0x09
125 # define STAT2_INT_SHFITS 3
126 # define STAT2_INT (1 << STAT2_INT_SHFITS)
127 
128 #define ADDR_CTRL1 0x0a
129 # define CTRL1_MODE_SHFITS 0
130 # define CTRL1_MODE_STDBY (0 << CTRL1_MODE_SHFITS)
131 # define CTRL1_MODE_SINGLE (1 << CTRL1_MODE_SHFITS)
132 
133 #define ADDR_CTRL2 0x0b
134 # define CTRL2_SRST_SHFITS 0 /* Begin POR (auto cleared) */
135 # define CTRL2_SRST (1 << CTRL2_SRST_SHFITS)
136 # define CTRL2_DRP_SHIFTS 2
137 # define CTRL2_DRP (1 << CTRL2_DRP_SHIFTS)
138 # define CTRL2_DREN_SHIFTS 3
139 # define CTRL2_DREN (1 << CTRL2_DREN_SHIFTS)
140 
141 #define ADDR_CTRL3 0x41
142 # define CTRL3_SAMPLEAVG_16 0x24 /* Sample Averaging 16 */
143 # define CTRL3_SAMPLEAVG_8 0x1b /* Sample Averaging 8 */
144 # define CTRL3_SAMPLEAVG_4 0x12 /* Sample Averaging 4 */
145 # define CTRL3_SAMPLEAVG_2 0x09 /* Sample Averaging 2 */
146 
147 #define ADDR_CTRL4 0x42
148 # define CTRL4_SRPD 0xC0 /* Set Reset Pulse Duration */
149 
150 #define ADDR_STR 0x0c
151 # define STR_SELF_TEST_SHFITS 6
152 # define STR_SELF_TEST_ON (1 << STR_SELF_TEST_SHFITS)
153 # define STR_SELF_TEST_OFF (0 << STR_SELF_TEST_SHFITS)
154 
155 #define ADDR_Y11_Low 0x9c
156 #define ADDR_Y11_High 0x9d
157 #define ADDR_Y12_Low 0x9e
158 #define ADDR_Y12_High 0x9f
159 #define ADDR_Y13_Low 0xa0
160 #define ADDR_Y13_High 0xa1
161 #define ADDR_Y21_Low 0xa2
162 #define ADDR_Y21_High 0xa3
163 #define ADDR_Y22_Low 0xa4
164 #define ADDR_Y22_High 0xa5
165 #define ADDR_Y23_Low 0xa6
166 #define ADDR_Y23_High 0xa7
167 #define ADDR_Y31_Low 0xa8
168 #define ADDR_Y31_High 0xa9
169 #define ADDR_Y32_Low 0xaa
170 #define ADDR_Y32_High 0xab
171 #define ADDR_Y33_Low 0xac
172 #define ADDR_Y33_High 0xad
173 
174 #define ADDR_TEMPL 0x1c
175 #define ADDR_TEMPH 0x1d
176 
184 };
185 
186 class IST8310 : public device::I2C, public px4::ScheduledWorkItem
187 {
188 public:
189  IST8310(int bus_number, int address, const char *path, enum Rotation rotation);
190  virtual ~IST8310();
191 
192  virtual int init();
193 
194  virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
195  virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
196 
197  /**
198  * Diagnostics - print some basic information about the driver.
199  */
200  void print_info();
201 
202 protected:
203  virtual int probe();
204 
205 private:
206 
207  unsigned _measure_interval{0};
208 
209  ringbuffer::RingBuffer *_reports{nullptr};
210 
212  float _range_scale{0.003f}; /* default range scale from counts to gauss */
213 
214  bool _collect_phase{false};
217 
219 
224 
225  /* status reporting */
226  bool _sensor_ok{false}; /**< sensor was found and reports ok */
227  bool _calibrated{false}; /**< the calibration is valid */
229 
230  sensor_mag_s _last_report{}; /**< used for info() */
231 
232  uint8_t _ctl3_reg{0};
233  uint8_t _ctl4_reg{0};
234 
235  /**
236  * Initialise the automatic measurement state machine and start it.
237  *
238  * @note This function is called at open and error time. It might make sense
239  * to make it more aggressive about resetting the bus in case of errors.
240  */
241  void start();
242 
243  /**
244  * Stop the automatic measurement state machine.
245  */
246  void stop();
247 
248  /**
249  * Reset the device
250  */
251  int reset();
252 
253  /**
254  * Perform the on-sensor scale calibration routine.
255  *
256  * @note The sensor will continue to provide measurements, these
257  * will however reflect the uncalibrated sensor state until
258  * the calibration routine has been completed.
259  *
260  * @param enable set to 1 to enable self-test strap, 0 to disable
261  */
262  int calibrate(struct file *filp, unsigned enable);
263 
264  /**
265  * check the sensor configuration.
266  *
267  * checks that the config of the sensor is correctly set, to
268  * cope with communication errors causing the configuration to
269  * change
270  */
271  void check_conf(void);
272 
273  /**
274  * Perform a poll cycle; collect from the previous measurement
275  * and start a new one.
276  *
277  * This is the heart of the measurement state machine. This function
278  * alternately starts a measurement, or collects the data from the
279  * previous measurement.
280  *
281  * When the interval between measurements is greater than the minimum
282  * measurement interval, a gap is inserted between collection
283  * and measurement to provide the most recent measurement possible
284  * at the next interval.
285  */
286  void Run() override;
287 
288  /**
289  * Write a register.
290  *
291  * @param reg The register to write.
292  * @param val The value to write.
293  * @return OK on write success.
294  */
295  int write_reg(uint8_t reg, uint8_t val);
296 
297  /**
298  * Write to a register block.
299  *
300  * @param address The register address to write to.
301  * @param data The buffer to write from.
302  * @param count The number of bytes to write.
303  * @return OK on write success.
304  */
305  int write(unsigned address, void *data, unsigned count);
306 
307  /**
308  * Read a register.
309  *
310  * @param reg The register to read.
311  * @param val The value read.
312  * @return OK on read success.
313  */
314  int read_reg(uint8_t reg, uint8_t &val);
315 
316  /**
317  * read register block.
318  *
319  * @param address The register address to read from.
320  * @param data The buffer to read into.
321  * @param count The number of bytes to read.
322  * @return OK on write success.
323  */
324  int read(unsigned address, void *data, unsigned count);
325 
326  /**
327  * Issue a measurement command.
328  *
329  * @return OK if the measurement command was successful.
330  */
331  int measure();
332 
333  /**
334  * Collect the result of the most recent measurement.
335  */
336  int collect();
337 
338  /**
339  * Convert a big-endian signed 16-bit value to a float.
340  *
341  * @param in A signed 16-bit big-endian value.
342  * @return The floating-point representation of the value.
343  */
344  float meas_to_float(uint8_t in[2]);
345 
346  /**
347  * Check the current scale calibration
348  *
349  * @return 0 if scale calibration is ok, 1 else
350  */
351  int check_scale();
352 
353  /**
354  * Check the current offset calibration
355  *
356  * @return 0 if offset calibration is ok, 1 else
357  */
358  int check_offset();
359 
360  /**
361  * Place the device in self test mode
362  *
363  * @return 0 if mode is set, 1 else
364  */
365  int set_selftest(unsigned enable);
366 
367  /* this class has pointer data members, do not allow copying it */
368  IST8310(const IST8310 &);
369  IST8310 operator=(const IST8310 &);
370 };
371 
372 /*
373  * Driver 'main' command.
374  */
375 extern "C" __EXPORT int ist8310_main(int argc, char *argv[]);
376 
377 
378 IST8310::IST8310(int bus_number, int address, const char *path, enum Rotation rotation) :
379  I2C("IST8310", path, bus_number, address, IST8310_DEFAULT_BUS_SPEED),
380  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(get_device_id())),
381  _sample_perf(perf_alloc(PC_ELAPSED, "ist8310_read")),
382  _comms_errors(perf_alloc(PC_COUNT, "ist8310_com_err")),
383  _range_errors(perf_alloc(PC_COUNT, "ist8310_rng_err")),
384  _conf_errors(perf_alloc(PC_COUNT, "ist8310_conf_err")),
385  _rotation(rotation)
386 {
387  _device_id.devid_s.devtype = DRV_MAG_DEVTYPE_IST8310;
388 
389  // default scaling
390  _scale.x_offset = 0;
391  _scale.x_scale = 1.0f;
392  _scale.y_offset = 0;
393  _scale.y_scale = 1.0f;
394  _scale.z_offset = 0;
395  _scale.z_scale = 1.0f;
396 }
397 
399 {
400  /* make sure we are truly inactive */
401  stop();
402 
403  if (_reports != nullptr) {
404  delete _reports;
405  }
406 
407  if (_class_instance != -1) {
408  unregister_class_devname(MAG_BASE_DEVICE_PATH, _class_instance);
409  }
410 
411  // free perf counters
416 }
417 
418 int
420 {
421  int ret = PX4_ERROR;
422 
423  ret = I2C::init();
424 
425  if (ret != OK) {
426  DEVICE_DEBUG("CDev init failed");
427  goto out;
428  }
429 
430  /* allocate basic report buffers */
431  _reports = new ringbuffer::RingBuffer(2, sizeof(mag_report));
432 
433  if (_reports == nullptr) {
434  goto out;
435  }
436 
437  /* reset the device configuration */
438  reset();
439 
440  _class_instance = register_class_devname(MAG_BASE_DEVICE_PATH);
441 
442  ret = OK;
443  /* sensor is ok, but not calibrated */
444  _sensor_ok = true;
445 out:
446  return ret;
447 }
448 
449 int
450 IST8310::write(unsigned address, void *data, unsigned count)
451 {
452  uint8_t buf[32];
453 
454  if (sizeof(buf) < (count + 1)) {
455  return -EIO;
456  }
457 
458  buf[0] = address;
459  memcpy(&buf[1], data, count);
460 
461  return transfer(&buf[0], count + 1, nullptr, 0);
462 }
463 
464 int
465 IST8310::read(unsigned address, void *data, unsigned count)
466 {
467  uint8_t cmd = address;
468  return transfer(&cmd, 1, (uint8_t *)data, count);
469 }
470 
471 
472 /**
473  check that the configuration register has the right value. This is
474  done periodically to cope with I2C bus noise causing the
475  configuration of the compass to change.
476  */
478 {
479  int ret;
480 
481  uint8_t ctrl_reg_in = 0;
482  ret = read_reg(ADDR_CTRL3, ctrl_reg_in);
483 
484  if (OK != ret) {
486  return;
487  }
488 
489  if (ctrl_reg_in != _ctl3_reg) {
492 
493  if (OK != ret) {
495  }
496  }
497 
498  ret = read_reg(ADDR_CTRL4, ctrl_reg_in);
499 
500  if (OK != ret) {
502  return;
503  }
504 
505  if (ctrl_reg_in != _ctl4_reg) {
508 
509  if (OK != ret) {
511  }
512  }
513 }
514 
515 ssize_t
516 IST8310::read(struct file *filp, char *buffer, size_t buflen)
517 {
518  unsigned count = buflen / sizeof(struct mag_report);
519  struct mag_report *mag_buf = reinterpret_cast<struct mag_report *>(buffer);
520  int ret = 0;
521 
522  /* buffer must be large enough */
523  if (count < 1) {
524  return -ENOSPC;
525  }
526 
527  /* if automatic measurement is enabled */
528  if (_measure_interval > 0) {
529  /*
530  * While there is space in the caller's buffer, and reports, copy them.
531  * Note that we may be pre-empted by the workq thread while we are doing this;
532  * we are careful to avoid racing with them.
533  */
534  while (count--) {
535  if (_reports->get(mag_buf)) {
536  ret += sizeof(struct mag_report);
537  mag_buf++;
538  }
539  }
540 
541  /* if there was no data, warn the caller */
542  return ret ? ret : -EAGAIN;
543  }
544 
545  /* manual measurement - run one conversion */
546  /* XXX really it'd be nice to lock against other readers here */
547  do {
548  _reports->flush();
549 
550  /* trigger a measurement */
551  if (OK != measure()) {
552  ret = -EIO;
553  break;
554  }
555 
556  /* wait for it to complete */
558 
559  /* run the collection phase */
560  if (OK != collect()) {
561  ret = -EIO;
562  break;
563  }
564 
565  if (_reports->get(mag_buf)) {
566  ret = sizeof(struct mag_report);
567  }
568  } while (0);
569 
570  return ret;
571 }
572 
573 int
574 IST8310::ioctl(struct file *filp, int cmd, unsigned long arg)
575 {
576  switch (cmd) {
577  case SENSORIOCSPOLLRATE: {
578  switch (arg) {
579 
580  /* zero would be bad */
581  case 0:
582  return -EINVAL;
583 
584  /* set default polling rate */
586  /* do we need to start internal polling? */
587  bool want_start = (_measure_interval == 0);
588 
589  /* set interval for next measurement to minimum legal value */
591 
592  /* if we need to start the poll state machine, do it */
593  if (want_start) {
594  start();
595  }
596 
597  return OK;
598  }
599 
600  /* adjust to a legal polling interval in Hz */
601  default: {
602  /* do we need to start internal polling? */
603  bool want_start = (_measure_interval == 0);
604 
605  /* convert hz to tick interval via microseconds */
606  unsigned interval = (1000000 / arg);
607 
608  /* check against maximum rate */
609  if (interval < IST8310_CONVERSION_INTERVAL) {
610  return -EINVAL;
611  }
612 
613  /* update interval for next measurement */
614  _measure_interval = interval;
615 
616  /* if we need to start the poll state machine, do it */
617  if (want_start) {
618  start();
619  }
620 
621  return OK;
622  }
623  }
624  }
625 
626  case SENSORIOCRESET:
627  return reset();
628 
629  case MAGIOCEXSTRAP:
630  return set_selftest(arg);
631 
632  case MAGIOCSSCALE:
633  /* set new scale factors */
634  memcpy(&_scale, (struct mag_calibration_s *)arg, sizeof(_scale));
635  return 0;
636 
637  case MAGIOCGSCALE:
638  /* copy out scale factors */
639  memcpy((struct mag_calibration_s *)arg, &_scale, sizeof(_scale));
640  return 0;
641 
642  case MAGIOCCALIBRATE:
643  return calibrate(filp, arg);
644 
645  case MAGIOCGEXTERNAL:
646  return external();
647 
648  default:
649  /* give it to the superclass */
650  return CDev::ioctl(filp, cmd, arg);
651  }
652 }
653 
654 void
656 {
657  /* reset the report ring and state machine */
658  _collect_phase = false;
659  _reports->flush();
660 
661  /* schedule a cycle to start things */
662  ScheduleNow();
663 }
664 
665 void
667 {
668  ScheduleClear();
669 }
670 
671 int
673 {
674  /* software reset */
676 
677  /* configure control register 3 */
680 
681  /* configure control register 4 */
684 
685  return OK;
686 }
687 
688 int
690 {
691  uint8_t data[1] = {0};
692 
693  _retries = 10;
694 
695  if (read(ADDR_WAI, &data[0], 1)) {
696  DEVICE_DEBUG("read_reg fail");
697  return -EIO;
698  }
699 
700  _retries = 2;
701 
702  if ((data[0] != WAI_EXPECTED_VALUE)) {
703  DEVICE_DEBUG("ID byte mismatch (%02x) expected %02x", data[0], WAI_EXPECTED_VALUE);
704  return -EIO;
705  }
706 
707  return OK;
708 }
709 
710 void
712 {
713  /* collection phase? */
714  if (_collect_phase) {
715 
716  /* perform collection */
717  if (OK != collect()) {
718  DEVICE_DEBUG("collection error");
719  /* restart the measurement state machine */
720  start();
721  return;
722  }
723 
724  /* next phase is measurement */
725  _collect_phase = false;
726 
727  /*
728  * Is there a collect->measure gap?
729  */
731 
732  /* schedule a fresh cycle call when we are ready to measure again */
734 
735  return;
736  }
737  }
738 
739  /* measurement phase */
740  if (OK != measure()) {
741  DEVICE_DEBUG("measure error");
742  }
743 
744  /* next phase is collection */
745  _collect_phase = true;
746 
747  /* schedule a fresh cycle call when the measurement is done */
748  ScheduleDelayed(IST8310_CONVERSION_INTERVAL);
749 }
750 
751 int
753 {
754  /*
755  * Send the command to begin a measurement.
756  */
758 
759  if (OK != ret) {
761  }
762 
763  return ret;
764 }
765 
766 int
768 {
769 #pragma pack(push, 1)
770  struct { /* status register and data as read back from the device */
771  uint8_t x[2];
772  uint8_t y[2];
773  uint8_t z[2];
774  } report_buffer;
775 #pragma pack(pop)
776  struct {
777  int16_t x, y, z;
778  } report;
779 
780  int ret;
781  uint8_t check_counter;
782 
784  struct mag_report new_report;
785  const bool sensor_is_external = external();
786 
787  float xraw_f;
788  float yraw_f;
789  float zraw_f;
790 
791  /* this should be fairly close to the end of the measurement, so the best approximation of the time */
792  new_report.timestamp = hrt_absolute_time();
793  new_report.is_external = sensor_is_external;
794  new_report.error_count = perf_event_count(_comms_errors);
795  new_report.scaling = _range_scale;
796  new_report.device_id = _device_id.devid;
797 
798  /*
799  * @note We could read the status register here, which could tell us that
800  * we were too early and that the output registers are still being
801  * written. In the common case that would just slow us down, and
802  * we're better off just never being early.
803  */
804 
805  /* get measurements from the device */
806  ret = read(ADDR_DATA_OUT_X_LSB, (uint8_t *)&report_buffer, sizeof(report_buffer));
807 
808  if (ret != OK) {
810  DEVICE_DEBUG("I2C read error");
811  goto out;
812  }
813 
814  /* swap the data we just received */
815  report.x = (((int16_t)report_buffer.x[1]) << 8) | (int16_t)report_buffer.x[0];
816  report.y = (((int16_t)report_buffer.y[1]) << 8) | (int16_t)report_buffer.y[0];
817  report.z = (((int16_t)report_buffer.z[1]) << 8) | (int16_t)report_buffer.z[0];
818 
819 
820  /*
821  * Check if value makes sense according to the FSR and Resolution of
822  * this sensor, discarding outliers
823  */
824  if (report.x > IST8310_MAX_VAL_XY || report.x < IST8310_MIN_VAL_XY ||
825  report.y > IST8310_MAX_VAL_XY || report.y < IST8310_MIN_VAL_XY ||
826  report.z > IST8310_MAX_VAL_Z || report.z < IST8310_MIN_VAL_Z) {
828  DEVICE_DEBUG("data/status read error");
829  goto out;
830  }
831 
832  /* temperature measurement is not available on IST8310 */
833  new_report.temperature = 0;
834 
835  /*
836  * raw outputs
837  *
838  * Sensor doesn't follow right hand rule, swap x and y to make it obey
839  * it.
840  */
841  new_report.x_raw = report.y;
842  new_report.y_raw = report.x;
843  new_report.z_raw = report.z;
844 
845  /* scale values for output */
846  xraw_f = report.y;
847  yraw_f = report.x;
848  zraw_f = report.z;
849 
850  /* apply user specified rotation */
851  rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);
852  new_report.x = ((xraw_f * _range_scale) - _scale.x_offset) * _scale.x_scale;
853  new_report.y = ((yraw_f * _range_scale) - _scale.y_offset) * _scale.y_scale;
854  new_report.z = ((zraw_f * _range_scale) - _scale.z_offset) * _scale.z_scale;
855 
856  if (!(_pub_blocked)) {
857 
858  if (_mag_topic != nullptr) {
859  /* publish it */
860  orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_report);
861 
862  } else {
863  _mag_topic = orb_advertise_multi(ORB_ID(sensor_mag), &new_report,
864  &_orb_class_instance, sensor_is_external ? ORB_PRIO_MAX : ORB_PRIO_HIGH);
865 
866  if (_mag_topic == nullptr) {
867  DEVICE_DEBUG("ADVERT FAIL");
868  }
869  }
870  }
871 
872  _last_report = new_report;
873 
874  /* post a report to the ring */
875  _reports->force(&new_report);
876 
877  /* notify anyone waiting for data */
878  poll_notify(POLLIN);
879 
880  /*
881  periodically check the range register and configuration
882  registers. With a bad I2C cable it is possible for the
883  registers to become corrupt, leading to bad readings. It
884  doesn't happen often, but given the poor cables some
885  vehicles have it is worth checking for.
886  */
887  check_counter = perf_event_count(_sample_perf) % 256;
888 
889  if (check_counter == 128) {
890  check_conf();
891  }
892 
893  ret = OK;
894 
895 out:
897  return ret;
898 }
899 
900 int IST8310::calibrate(struct file *filp, unsigned enable)
901 {
902  struct mag_report report {};
903  ssize_t sz;
904  int ret = 1;
905  float total_x = 0.0f;
906  float total_y = 0.0f;
907  float total_z = 0.0f;
908 
909  // XXX do something smarter here
910  int fd = (int)enable;
911 
912  struct mag_calibration_s mscale_previous;
913 
914  struct mag_calibration_s mscale_null;
915  mscale_null.x_offset = 0.0f;
916  mscale_null.x_scale = 1.0f;
917  mscale_null.y_offset = 0.0f;
918  mscale_null.y_scale = 1.0f;
919  mscale_null.z_offset = 0.0f;
920  mscale_null.z_scale = 1.0f;
921 
922  float sum_in_test[3] = {0.0f, 0.0f, 0.0f};
923  float sum_in_normal[3] = {0.0f, 0.0f, 0.0f};
924  float *sum = &sum_in_normal[0];
925 
926  if (OK != ioctl(filp, MAGIOCGSCALE, (long unsigned int)&mscale_previous)) {
927  PX4_WARN("FAILED: MAGIOCGSCALE 1");
928  ret = 1;
929  goto out;
930  }
931 
932  if (OK != ioctl(filp, MAGIOCSSCALE, (long unsigned int)&mscale_null)) {
933  PX4_WARN("FAILED: MAGIOCSSCALE 1");
934  ret = 1;
935  goto out;
936  }
937 
938  /* start the sensor polling at 50 Hz */
939  if (OK != ioctl(filp, SENSORIOCSPOLLRATE, 50)) {
940  PX4_WARN("FAILED: SENSORIOCSPOLLRATE 50Hz");
941  ret = 1;
942  goto out;
943  }
944 
945  // discard 10 samples to let the sensor settle
946  /* read the sensor 50 times */
947 
948  for (uint8_t p = 0; p < 2; p++) {
949 
950  if (p == 1) {
951 
952  /* start the Self test */
953 
954  if (OK != ioctl(filp, MAGIOCEXSTRAP, 1)) {
955  PX4_WARN("FAILED: MAGIOCEXSTRAP 1");
956  ret = 1;
957  goto out;
958  }
959 
960  sum = &sum_in_test[0];
961  }
962 
963 
964  for (uint8_t i = 0; i < 30; i++) {
965 
966 
967  struct pollfd fds;
968 
969  /* wait for data to be ready */
970  fds.fd = fd;
971  fds.events = POLLIN;
972  ret = ::poll(&fds, 1, 2000);
973 
974  if (ret != 1) {
975  PX4_WARN("ERROR: TIMEOUT 2");
976  goto out;
977  }
978 
979  /* now go get it */
980 
981  sz = ::read(fd, &report, sizeof(report));
982 
983  if (sz != sizeof(report)) {
984  PX4_WARN("ERROR: READ 2");
985  ret = -EIO;
986  goto out;
987  }
988 
989  if (i > 10) {
990  sum[0] += report.x_raw;
991  sum[1] += report.y_raw;
992  sum[2] += report.z_raw;
993  }
994  }
995  }
996 
997  total_x = fabsf(sum_in_test[0] - sum_in_normal[0]);
998  total_y = fabsf(sum_in_test[1] - sum_in_normal[1]);
999  total_z = fabsf(sum_in_test[2] - sum_in_normal[2]);
1000 
1001  ret = ((total_x + total_y + total_z) < (float)0.000001);
1002 
1003 out:
1004 
1005  if (OK != ioctl(filp, MAGIOCSSCALE, (long unsigned int)&mscale_previous)) {
1006  PX4_WARN("FAILED: MAGIOCSSCALE 2");
1007  }
1008 
1009  /* set back to normal mode */
1010 
1011  if (OK != ::ioctl(fd, MAGIOCEXSTRAP, 0)) {
1012  PX4_WARN("FAILED: MAGIOCEXSTRAP 0");
1013  }
1014 
1015  if (ret == OK) {
1016  if (check_scale()) {
1017  /* failed */
1018  PX4_WARN("FAILED: SCALE");
1019  ret = PX4_ERROR;
1020  }
1021 
1022  } else {
1023  PX4_ERR("FAILED: CALIBRATION SCALE %d, %d, %d", (int)total_x, (int)total_y, (int)total_z);
1024  }
1025 
1026  return ret;
1027 }
1028 
1030 {
1031  return OK;
1032 }
1033 
1035 {
1036  bool offset_valid;
1037 
1038  if ((-2.0f * FLT_EPSILON < _scale.x_offset && _scale.x_offset < 2.0f * FLT_EPSILON) &&
1039  (-2.0f * FLT_EPSILON < _scale.y_offset && _scale.y_offset < 2.0f * FLT_EPSILON) &&
1040  (-2.0f * FLT_EPSILON < _scale.z_offset && _scale.z_offset < 2.0f * FLT_EPSILON)) {
1041  /* offset is zero */
1042  offset_valid = false;
1043 
1044  } else {
1045  offset_valid = true;
1046  }
1047 
1048  /* return 0 if calibrated, 1 else */
1049  return !offset_valid;
1050 }
1051 
1052 int
1053 IST8310::set_selftest(unsigned enable)
1054 {
1055  int ret;
1056  uint8_t str;
1057  /* arm the excitement strap */
1058  ret = read_reg(ADDR_STR, str);
1059 
1060  if (OK != ret) {
1062  }
1063 
1064  str &= ~STR_SELF_TEST_ON; // reset previous test
1065 
1066  if (enable > 0) {
1067  str |= STR_SELF_TEST_ON;
1068 
1069  }
1070 
1071  ret = write_reg(ADDR_STR, str);
1072 
1073  if (OK != ret) {
1075  }
1076 
1077  uint8_t str_reg_ret = 0;
1078  read_reg(ADDR_STR, str_reg_ret);
1079 
1080  return !(str == str_reg_ret);
1081 }
1082 
1083 int
1084 IST8310::write_reg(uint8_t reg, uint8_t val)
1085 {
1086  uint8_t buf = val;
1087  return write(reg, &buf, 1);
1088 }
1089 
1090 int
1091 IST8310::read_reg(uint8_t reg, uint8_t &val)
1092 {
1093  uint8_t buf = val;
1094  int ret = read(reg, &buf, 1);
1095  val = buf;
1096  return ret;
1097 }
1098 
1099 float
1101 {
1102  union {
1103  uint8_t b[2];
1104  int16_t w;
1105  } u;
1106 
1107  u.b[0] = in[1];
1108  u.b[1] = in[0];
1109 
1110  return (float) u.w;
1111 }
1112 
1113 void
1115 {
1118  printf("poll interval: %u interval\n", _measure_interval);
1119  print_message(_last_report);
1120  _reports->print_info("report queue");
1121 }
1122 
1123 /**
1124  * Local functions in support of the shell command.
1125  */
1126 namespace ist8310
1127 {
1128 
1129 /*
1130  list of supported bus configurations
1131  */
1133  enum IST8310_BUS busid;
1134  const char *devpath;
1135  uint8_t busnum;
1137 } bus_options[] = {
1138  { IST8310_BUS_I2C_EXTERNAL, "/dev/ist8310_ext", PX4_I2C_BUS_EXPANSION, NULL },
1139 #ifdef PX4_I2C_BUS_EXPANSION1
1140  { IST8310_BUS_I2C_EXTERNAL1, "/dev/ist8311_ext1", PX4_I2C_BUS_EXPANSION1, NULL },
1141 #endif
1142 #ifdef PX4_I2C_BUS_EXPANSION2
1143  { IST8310_BUS_I2C_EXTERNAL2, "/dev/ist8312_ext2", PX4_I2C_BUS_EXPANSION2, NULL },
1144 #endif
1145 #ifdef PX4_I2C_BUS_ONBOARD
1146  { IST8310_BUS_I2C_INTERNAL, "/dev/ist8310_int", PX4_I2C_BUS_ONBOARD, NULL },
1147 #endif
1148 };
1149 #define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0]))
1150 
1151 void start(enum IST8310_BUS busid, int address, enum Rotation rotation);
1152 bool start_bus(struct ist8310_bus_option &bus, int address, enum Rotation rotation);
1153 struct ist8310_bus_option &find_bus(enum IST8310_BUS busid);
1154 void test(enum IST8310_BUS busid);
1155 void reset(enum IST8310_BUS busid);
1156 int info(enum IST8310_BUS busid);
1157 int calibrate(enum IST8310_BUS busid);
1158 void usage();
1159 
1160 /**
1161  * start driver for a specific bus option
1162  */
1163 bool
1164 start_bus(struct ist8310_bus_option &bus, int address, enum Rotation rotation)
1165 {
1166  if (bus.dev != nullptr) {
1167  errx(1, "bus option already started");
1168  }
1169 
1170  IST8310 *interface = new IST8310(bus.busnum, address, bus.devpath, rotation);
1171 
1172  if (interface->init() != OK) {
1173  delete interface;
1174  PX4_INFO("no device on bus %u", (unsigned)bus.busid);
1175  return false;
1176  }
1177 
1178  bus.dev = interface;
1179 
1180  int fd = open(bus.devpath, O_RDONLY);
1181 
1182  if (fd < 0) {
1183  return false;
1184  }
1185 
1187  close(fd);
1188  errx(1, "Failed to setup poll rate");
1189  }
1190 
1191  close(fd);
1192 
1193  return true;
1194 }
1195 
1196 
1197 /**
1198  * Start the driver.
1199  *
1200  * This function call only returns once the driver
1201  * is either successfully up and running or failed to start.
1202  */
1203 void
1204 start(enum IST8310_BUS busid, int address, enum Rotation rotation)
1205 {
1206  bool started = false;
1207 
1208  for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) {
1209  if (busid == IST8310_BUS_ALL && bus_options[i].dev != NULL) {
1210  // this device is already started
1211  continue;
1212  }
1213 
1214  if (busid != IST8310_BUS_ALL && bus_options[i].busid != busid) {
1215  // not the one that is asked for
1216  continue;
1217  }
1218 
1219  started |= start_bus(bus_options[i], address, rotation);
1220  }
1221 
1222  if (!started) {
1223  exit(1);
1224  }
1225 }
1226 
1227 /**
1228  * find a bus structure for a busid
1229  */
1231 {
1232  for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) {
1233  if ((busid == IST8310_BUS_ALL ||
1234  busid == bus_options[i].busid) && bus_options[i].dev != NULL) {
1235  return bus_options[i];
1236  }
1237  }
1238 
1239  errx(1, "bus %u not started", (unsigned)busid);
1240 }
1241 
1242 
1243 /**
1244  * Perform some basic functional tests on the driver;
1245  * make sure we can collect data from the sensor in polled
1246  * and automatic modes.
1247  */
1248 void
1249 test(enum IST8310_BUS busid)
1250 {
1251  struct ist8310_bus_option &bus = find_bus(busid);
1252  struct mag_report report {};
1253  ssize_t sz;
1254  int ret;
1255  const char *path = bus.devpath;
1256 
1257  int fd = open(path, O_RDONLY);
1258 
1259  if (fd < 0) {
1260  err(1, "%s open failed (try 'ist8310 start')", path);
1261  }
1262 
1263  /* do a simple demand read */
1264  sz = read(fd, &report, sizeof(report));
1265 
1266  if (sz != sizeof(report)) {
1267  err(1, "immediate read failed");
1268  }
1269 
1270  print_message(report);
1271 
1272  /* check if mag is onboard or external */
1273  if ((ret = ioctl(fd, MAGIOCGEXTERNAL, 0)) < 0) {
1274  errx(1, "failed to get if mag is onboard or external");
1275  }
1276 
1277  /* read the sensor 5x and report each value */
1278  for (unsigned i = 0; i < 5; i++) {
1279  struct pollfd fds;
1280 
1281  /* wait for data to be ready */
1282  fds.fd = fd;
1283  fds.events = POLLIN;
1284  ret = poll(&fds, 1, 2000);
1285 
1286  if (ret != 1) {
1287  errx(1, "timed out waiting for sensor data");
1288  }
1289 
1290  /* now go get it */
1291  sz = read(fd, &report, sizeof(report));
1292 
1293  if (sz != sizeof(report)) {
1294  err(1, "periodic read failed");
1295  }
1296 
1297  print_message(report);
1298  }
1299 
1300  PX4_INFO("PASS");
1301  exit(0);
1302 }
1303 
1304 
1305 /**
1306  * Automatic scale calibration.
1307  *
1308  * Basic idea:
1309  *
1310  * output = (ext field +- 1.1 Ga self-test) * scale factor
1311  *
1312  * and consequently:
1313  *
1314  * 1.1 Ga = (excited - normal) * scale factor
1315  * scale factor = (excited - normal) / 1.1 Ga
1316  *
1317  * sxy = (excited - normal) / 766 | for conf reg. B set to 0x60 / Gain = 3
1318  * sz = (excited - normal) / 713 | for conf reg. B set to 0x60 / Gain = 3
1319  *
1320  * By subtracting the non-excited measurement the pure 1.1 Ga reading
1321  * can be extracted and the sensitivity of all axes can be matched.
1322  *
1323  * SELF TEST OPERATION
1324  * To check the IST8310L for proper operation, a self test feature in incorporated
1325  * in which the sensor will change the polarity on all 3 axis. The values with and
1326  * with and without selftest on shoult be compared and if the absolete value are equal
1327  * the IC is functional.
1328  */
1329 int calibrate(enum IST8310_BUS busid)
1330 {
1331  int ret;
1332  struct ist8310_bus_option &bus = find_bus(busid);
1333  const char *path = bus.devpath;
1334 
1335  int fd = open(path, O_RDONLY);
1336 
1337  if (fd < 0) {
1338  err(1, "%s open failed (try 'ist8310 start' if the driver is not running", path);
1339  }
1340 
1341  if (OK != (ret = ioctl(fd, MAGIOCCALIBRATE, fd))) {
1342  PX4_WARN("failed to enable sensor calibration mode");
1343  }
1344 
1345  close(fd);
1346 
1347  return ret;
1348 }
1349 
1350 /**
1351  * Reset the driver.
1352  */
1353 void
1354 reset(enum IST8310_BUS busid)
1355 {
1356  struct ist8310_bus_option &bus = find_bus(busid);
1357  const char *path = bus.devpath;
1358 
1359  int fd = open(path, O_RDONLY);
1360 
1361  if (fd < 0) {
1362  err(1, "failed ");
1363  }
1364 
1365  if (ioctl(fd, SENSORIOCRESET, 0) < 0) {
1366  err(1, "driver reset failed");
1367  }
1368 
1370  err(1, "driver poll restart failed");
1371  }
1372 
1373  // Relay on at_)exit to close handel
1374  exit(0);
1375 }
1376 
1377 
1378 
1379 /**
1380  * Print a little info about the driver.
1381  */
1382 int
1383 info(enum IST8310_BUS busid)
1384 {
1385  struct ist8310_bus_option &bus = find_bus(busid);
1386 
1387  PX4_INFO("running on bus: %u (%s)\n", (unsigned)bus.busid, bus.devpath);
1388  bus.dev->print_info();
1389  exit(0);
1390 }
1391 
1392 void
1394 {
1395  PX4_INFO("missing command: try 'start', 'info', 'test', 'reset', 'calibrate'");
1396  PX4_INFO("options:");
1397  PX4_INFO(" -R rotation");
1398  PX4_INFO(" -C calibrate on start");
1399  PX4_INFO(" -a 12C Address (0x%02x)", IST8310_BUS_I2C_ADDR);
1400  PX4_INFO(" -b 12C bus (%d-%d)", IST8310_BUS_I2C_EXTERNAL, IST8310_BUS_I2C_INTERNAL);
1401 }
1402 
1403 } // namespace
1404 
1405 int
1406 ist8310_main(int argc, char *argv[])
1407 {
1408  IST8310_BUS i2c_busid = IST8310_BUS_ALL;
1409  int i2c_addr = IST8310_BUS_I2C_ADDR; /* 7bit */
1410 
1411  enum Rotation rotation = ROTATION_NONE;
1412  bool calibrate = false;
1413  int myoptind = 1;
1414  int ch;
1415  const char *myoptarg = nullptr;
1416 
1417  while ((ch = px4_getopt(argc, argv, "R:Ca:b:", &myoptind, &myoptarg)) != EOF) {
1418  switch (ch) {
1419  case 'R':
1420  rotation = (enum Rotation)atoi(myoptarg);
1421  break;
1422 
1423  case 'a':
1424  i2c_addr = (int)strtol(myoptarg, NULL, 0);
1425  break;
1426 
1427  case 'b':
1428  i2c_busid = (IST8310_BUS)strtol(myoptarg, NULL, 0);
1429  break;
1430 
1431  case 'C':
1432  calibrate = true;
1433  break;
1434 
1435  default:
1436  ist8310::usage();
1437  exit(0);
1438  }
1439  }
1440 
1441  if (myoptind >= argc) {
1442  ist8310::usage();
1443  return 1;
1444  }
1445 
1446  const char *verb = argv[myoptind];
1447 
1448  /*
1449  * Start/load the driver.
1450  */
1451  if (!strcmp(verb, "start")) {
1452  ist8310::start(i2c_busid, i2c_addr, rotation);
1453 
1454  if (i2c_busid == IST8310_BUS_ALL) {
1455  PX4_ERR("calibration only feasible against one bus");
1456  return 1;
1457 
1458  } else if (calibrate && (ist8310::calibrate(i2c_busid) != 0)) {
1459  PX4_ERR("calibration failed");
1460  return 1;
1461  }
1462 
1463  return 0;
1464  }
1465 
1466  /*
1467  * Test the driver/device.
1468  */
1469  if (!strcmp(verb, "test")) {
1470  ist8310::test(i2c_busid);
1471  }
1472 
1473  /*
1474  * Reset the driver.
1475  */
1476  if (!strcmp(verb, "reset")) {
1477  ist8310::reset(i2c_busid);
1478  }
1479 
1480  /*
1481  * Print driver information.
1482  */
1483  if (!strcmp(verb, "info") || !strcmp(verb, "status")) {
1484  ist8310::info(i2c_busid);
1485  }
1486 
1487  /*
1488  * Autocalibrate the scaling
1489  */
1490  if (!strcmp(verb, "calibrate")) {
1491  if (ist8310::calibrate(i2c_busid) == 0) {
1492  PX4_INFO("calibration successful");
1493  return 0;
1494 
1495  } else {
1496  PX4_ERR("calibration failed");
1497  return 1;
1498  }
1499  }
1500 
1501  ist8310::usage();
1502  return 1;
1503 }
perf_counter_t _conf_errors
Definition: ist8310.cpp:223
#define CTRL3_SAMPLEAVG_16
Definition: ist8310.cpp:142
int _class_instance
Definition: ist8310.cpp:215
#define MAGIOCGSCALE
copy the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:76
#define CTRL1_MODE_SINGLE
Definition: ist8310.cpp:131
#define MAGIOCGEXTERNAL
determine if mag is external or onboard
Definition: drv_mag.h:88
#define IST8310_DEFAULT_BUS_SPEED
Definition: ist8310.cpp:90
perf_counter_t _range_errors
Definition: ist8310.cpp:222
void start(enum IST8310_BUS busid, int address, enum Rotation rotation)
Start the driver.
Definition: ist8310.cpp:1204
void check_conf(void)
check the sensor configuration.
Definition: ist8310.cpp:477
measure the time elapsed performing an event
Definition: perf_counter.h:56
API for the uORB lightweight object broker.
__EXPORT int ist8310_main(int argc, char *argv[])
Definition: ist8310.cpp:1406
perf_counter_t _comms_errors
Definition: ist8310.cpp:221
#define MAGIOCEXSTRAP
excite strap
Definition: drv_mag.h:85
#define CTRL2_SRST
Definition: ist8310.cpp:135
uint8_t _ctl3_reg
Definition: ist8310.cpp:232
#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
void usage(const char *reason)
Print the correct usage.
Definition: Commander.cpp:4238
virtual int ioctl(struct file *filp, int cmd, unsigned long arg)
Definition: ist8310.cpp:574
Definition: I2C.hpp:51
int write_reg(uint8_t reg, uint8_t val)
Write a register.
Definition: ist8310.cpp:1084
mag scaling factors; Vout = (Vin * Vscale) + Voffset
Definition: drv_mag.h:56
bool _collect_phase
Definition: ist8310.cpp:214
#define STR_SELF_TEST_ON
Definition: ist8310.cpp:152
void start()
Initialise the automatic measurement state machine and start it.
Definition: ist8310.cpp:655
#define CTRL4_SRPD
Definition: ist8310.cpp:148
int calibrate(struct file *filp, unsigned enable)
Perform the on-sensor scale calibration routine.
Definition: ist8310.cpp:900
int check_scale()
Check the current scale calibration.
Definition: ist8310.cpp:1029
count the number of times an event occurs
Definition: perf_counter.h:55
static const int16_t IST8310_MAX_VAL_Z
Definition: ist8310.cpp:103
Vector rotation library.
#define FLT_EPSILON
High-resolution timer with callouts and timekeeping.
int reset()
Reset the device.
Definition: ist8310.cpp:672
int info(enum IST8310_BUS busid)
Print a little info about the driver.
Definition: ist8310.cpp:1383
void usage()
Prints info about the driver argument usage.
Definition: ist8310.cpp:1393
enum Rotation _rotation
Definition: ist8310.cpp:228
float x_offset
Definition: drv_mag.h:57
void test(enum IST8310_BUS busid)
Perform some basic functional tests on the driver; make sure we can collect data from the sensor in p...
Definition: ist8310.cpp:1249
#define IST8310_BUS_I2C_ADDR
Definition: ist8310.cpp:89
#define SENSORIOCSPOLLRATE
Set the driver polling rate to (arg) Hz, or one of the SENSOR_POLLRATE constants. ...
Definition: drv_sensor.h:134
#define ADDR_STR
Definition: ist8310.cpp:150
Generic device / sensor interface.
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
#define IST8310_CONVERSION_INTERVAL
Definition: ist8310.cpp:87
sensor_mag_s _last_report
used for info()
Definition: ist8310.cpp:230
void perf_count(perf_counter_t handle)
Count a performance event.
#define MAGIOCSSCALE
set the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:73
Header common to all counters.
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
int write(unsigned address, void *data, unsigned count)
Write to a register block.
Definition: ist8310.cpp:450
Local functions in support of the shell command.
Definition: ist8310.cpp:1126
void stop()
Stop the automatic measurement state machine.
Definition: ist8310.cpp:666
#define IST8310_RESOLUTION
Definition: ist8310.cpp:99
int set_selftest(unsigned enable)
Place the device in self test mode.
Definition: ist8310.cpp:1053
#define perf_alloc(a, b)
Definition: px4io.h:59
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
static const int16_t IST8310_MAX_VAL_XY
Definition: ist8310.cpp:101
uint8_t * data
Definition: dataman.cpp:149
#define ADDR_CTRL3
Definition: ist8310.cpp:141
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: ist8310.cpp:218
int _orb_class_instance
Definition: ist8310.cpp:216
virtual ~IST8310()
Definition: ist8310.cpp:398
float y_offset
Definition: drv_mag.h:59
void reset(enum IST8310_BUS busid)
Reset the driver.
Definition: ist8310.cpp:1354
bool _calibrated
the calibration is valid
Definition: ist8310.cpp:227
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
int calibrate(enum IST8310_BUS busid)
Automatic scale calibration.
Definition: ist8310.cpp:1329
void perf_end(perf_counter_t handle)
End a performance event.
#define NUM_BUS_OPTIONS
Definition: ist8310.cpp:1149
perf_counter_t _sample_perf
Definition: ist8310.cpp:220
IST8310_BUS
Definition: ist8310.cpp:177
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
#define ADDR_DATA_OUT_X_LSB
Definition: ist8310.cpp:117
int fd
Definition: dataman.cpp:146
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
IST8310 operator=(const IST8310 &)
#define err(eval,...)
Definition: err.h:83
float z_offset
Definition: drv_mag.h:61
#define ADDR_CTRL4
Definition: ist8310.cpp:147
virtual int init()
Definition: ist8310.cpp:419
bool start_bus(struct ist8310_bus_option &bus, int address, enum Rotation rotation)
start driver for a specific bus option
Definition: ist8310.cpp:1164
static const int16_t IST8310_MIN_VAL_XY
Definition: ist8310.cpp:102
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen)
Definition: ist8310.cpp:516
void print_info()
Diagnostics - print some basic information about the driver.
Definition: ist8310.cpp:1114
#define ADDR_CTRL2
Definition: ist8310.cpp:133
struct @83::@85::@87 file
float _range_scale
Definition: ist8310.cpp:212
IST8310(int bus_number, int address, const char *path, enum Rotation rotation)
Definition: ist8310.cpp:378
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.
struct ist8310_bus_option & find_bus(enum IST8310_BUS busid)
find a bus structure for a busid
Definition: ist8310.cpp:1230
#define errx(eval,...)
Definition: err.h:89
uint8_t _ctl4_reg
Definition: ist8310.cpp:233
Definition: bst.cpp:62
int check_offset()
Check the current offset calibration.
Definition: ist8310.cpp:1034
float meas_to_float(uint8_t in[2])
Convert a big-endian signed 16-bit value to a float.
Definition: ist8310.cpp:1100
bool _sensor_ok
sensor was found and reports ok
Definition: ist8310.cpp:226
ringbuffer::RingBuffer * _reports
Definition: ist8310.cpp:209
#define OK
Definition: uavcan_main.cpp:71
int collect()
Collect the result of the most recent measurement.
Definition: ist8310.cpp:767
enum IST8310_BUS busid
Definition: ist8310.cpp:1133
static const int16_t IST8310_MIN_VAL_Z
Definition: ist8310.cpp:104
#define WAI_EXPECTED_VALUE
Definition: ist8310.cpp:109
int read_reg(uint8_t reg, uint8_t &val)
Read a register.
Definition: ist8310.cpp:1091
#define ADDR_CTRL1
Definition: ist8310.cpp:128
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
void Run() override
Perform a poll cycle; collect from the previous measurement and start a new one.
Definition: ist8310.cpp:711
virtual int probe()
Definition: ist8310.cpp:689
void perf_begin(perf_counter_t handle)
Begin a performance event.
struct ist8310::ist8310_bus_option bus_options[]
#define DEVICE_DEBUG(FMT,...)
Definition: Device.hpp:52
#define DRV_MAG_DEVTYPE_IST8310
Definition: drv_sensor.h:60
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
#define ADDR_WAI
Definition: ist8310.cpp:108
unsigned _measure_interval
Definition: ist8310.cpp:207
Performance measuring tools.
int measure()
Issue a measurement command.
Definition: ist8310.cpp:752
Base class for devices connected via I2C.
#define mag_report
Definition: drv_mag.h:53