Firmware
mag.h
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 #pragma once
35 
36 #include "drivers/device/ringbuffer.h" // ringbuffer::RingBuffer
37 #include "drivers/drv_mag.h" // mag_calibration_s
38 #include <perf/perf_counter.h>
39 
40 /* in 16-bit sampling mode the mag resolution is 1.5 milli Gauss per bit */
41 
42 #define MPU9250_MAG_RANGE_GA 1.5e-3f;
43 
44 /* we are using the continuous fixed sampling rate of 100Hz */
45 
46 #define MPU9250_AK8963_SAMPLE_RATE 100
47 
48 /* ak8963 register address and bit definitions */
49 
50 #define AK8963_I2C_ADDR 0x0C
51 #define AK8963_DEVICE_ID 0x48
52 
53 #define AK8963REG_WIA 0x00
54 #define AK8963REG_ST1 0x02
55 #define AK8963REG_HXL 0x03
56 #define AK8963REG_ASAX 0x10
57 #define AK8963REG_CNTL1 0x0A
58 #define AK8963REG_CNTL2 0x0B
59 
60 #define AK8963_SINGLE_MEAS_MODE 0x01
61 #define AK8963_CONTINUOUS_MODE1 0x02
62 #define AK8963_CONTINUOUS_MODE2 0x06
63 #define AK8963_POWERDOWN_MODE 0x00
64 #define AK8963_SELFTEST_MODE 0x08
65 #define AK8963_FUZE_MODE 0x0F
66 #define AK8963_16BIT_ADC 0x10
67 #define AK8963_14BIT_ADC 0x00
68 #define AK8963_RESET 0x01
69 #define AK8963_HOFL 0x08
70 
71 /* ak09916 deviating register addresses and bit definitions */
72 
73 #define AK09916_DEVICE_ID_A 0x48 // same as AK8963
74 #define AK09916_DEVICE_ID_B 0x09 // additional ID byte ("INFO" on AK9063 without content specification.)
75 
76 #define AK09916REG_HXL 0x11
77 #define AK09916REG_HXH 0x12
78 #define AK09916REG_HYL 0x13
79 #define AK09916REG_HYH 0x14
80 #define AK09916REG_HZL 0x15
81 #define AK09916REG_HZH 0x16
82 #define AK09916REG_ST1 0x10
83 #define AK09916REG_ST2 0x18
84 #define AK09916REG_CNTL2 0x31
85 #define AK09916REG_CNTL3 0x32
86 
87 
88 #define AK09916_CNTL2_POWERDOWN_MODE 0x00
89 #define AK09916_CNTL2_SINGLE_MODE 0x01 /* default */
90 #define AK09916_CNTL2_CONTINOUS_MODE_10HZ 0x02
91 #define AK09916_CNTL2_CONTINOUS_MODE_20HZ 0x04
92 #define AK09916_CNTL2_CONTINOUS_MODE_50HZ 0x06
93 #define AK09916_CNTL2_CONTINOUS_MODE_100HZ 0x08
94 #define AK09916_CNTL2_SELFTEST_MODE 0x10
95 #define AK09916_CNTL3_SRST 0x01
96 #define AK09916_ST1_DRDY 0x01
97 #define AK09916_ST1_DOR 0x02
98 
99 class MPU9250;
100 
101 #pragma pack(push, 1)
102 struct ak8963_regs {
103  uint8_t st1;
104  int16_t x;
105  int16_t y;
106  int16_t z;
107  uint8_t st2;
108 };
109 #pragma pack(pop)
110 
111 #pragma pack(push, 1)
112 struct ak09916_regs {
113  uint8_t st1;
114  int16_t x;
115  int16_t y;
116  int16_t z;
117  uint8_t tmps;
118  uint8_t st2;
119 };
120 #pragma pack(pop)
121 
122 
123 extern device::Device *AK8963_I2C_interface(int bus, bool external_bus);
124 
125 typedef device::Device *(*MPU9250_mag_constructor)(int, bool);
126 
127 
131 class MPU9250_mag : public device::CDev
132 {
133 public:
134  MPU9250_mag(MPU9250 *parent, device::Device *interface, const char *path);
135  ~MPU9250_mag();
136 
137  virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
138  virtual int init();
139 
140  void set_passthrough(uint8_t reg, uint8_t size, uint8_t *out = NULL);
141  void passthrough_read(uint8_t reg, uint8_t *buf, uint8_t size);
142  void passthrough_write(uint8_t reg, uint8_t val);
143  void read_block(uint8_t reg, uint8_t *val, uint8_t count);
144 
145  int ak8963_reset(void);
146  int ak8963_setup(void);
147  int ak8963_setup_master_i2c(void);
148  bool ak8963_check_id(uint8_t &id);
149  bool ak8963_read_adjustments(void);
150 
151 protected:
152  Device *_interface;
153 
154  friend class MPU9250;
155 
156  /* Directly measure from the _interface if possible */
157  void measure();
158 
159  /* Update the state with prefetched data (internally called by the regular measure() )*/
160  void _measure(struct ak8963_regs data);
161 
162  uint8_t read_reg(unsigned reg);
163  void write_reg(unsigned reg, uint8_t value);
164 
165  bool is_passthrough() { return _interface == nullptr; }
166 
167 private:
168  MPU9250 *_parent;
169  orb_advert_t _mag_topic;
170  int _mag_orb_class_instance;
171  int _mag_class_instance;
172  bool _mag_reading_data;
173  ringbuffer::RingBuffer *_mag_reports;
174  struct mag_calibration_s _mag_scale;
175  float _mag_range_scale;
176  perf_counter_t _mag_reads;
177  perf_counter_t _mag_errors;
178  perf_counter_t _mag_overruns;
179  perf_counter_t _mag_overflows;
180  perf_counter_t _mag_duplicates;
181  float _mag_asa_x;
182  float _mag_asa_y;
183  float _mag_asa_z;
184 
185  bool check_duplicate(uint8_t *mag_data);
186 
187  // keep last mag reading for duplicate detection
188  uint8_t _last_mag_data[6];
189 
190  /* do not allow to copy this class due to pointer data members */
191  MPU9250_mag(const MPU9250_mag &);
192  MPU9250_mag operator=(const MPU9250_mag &);
193 };
A flexible ringbuffer class.
Definition: mag.h:103
mag scaling factors; Vout = (Vin * Vscale) + Voffset
Definition: drv_mag.h:56
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
Abstract class for any character device.
Definition: CDev.hpp:60
Header common to all counters.
Definition: perf_counter.cpp:65
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
Definition: mpu9250.h:256
Helper class implementing the magnetometer driver node.
Definition: mag.h:131
Definition: mag.h:113
Performance measuring tools.