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 
100 class ICM20948;
101 
102 #pragma pack(push, 1)
103 struct ak8963_regs {
104  uint8_t st1;
105  int16_t x;
106  int16_t y;
107  int16_t z;
108  uint8_t st2;
109 };
110 #pragma pack(pop)
111 
112 #pragma pack(push, 1)
113 struct ak09916_regs {
114  uint8_t st1;
115  int16_t x;
116  int16_t y;
117  int16_t z;
118  uint8_t tmps;
119  uint8_t st2;
120 };
121 #pragma pack(pop)
122 
123 
124 extern device::Device *AK8963_I2C_interface(int bus, bool external_bus);
125 
126 typedef device::Device *(*ICM20948_mag_constructor)(int, bool);
127 
128 
133 {
134 public:
135  ICM20948_mag(ICM20948 *parent, device::Device *interface, const char *path);
136  ~ICM20948_mag();
137 
138  virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
139  virtual int init();
140 
141  void set_passthrough(uint8_t reg, uint8_t size, uint8_t *out = NULL);
142  void passthrough_read(uint8_t reg, uint8_t *buf, uint8_t size);
143  void passthrough_write(uint8_t reg, uint8_t val);
144  void read_block(uint8_t reg, uint8_t *val, uint8_t count);
145 
146  int ak8963_reset(void);
147  int ak8963_setup(void);
148  int ak8963_setup_master_i2c(void);
149  bool ak8963_check_id(uint8_t &id);
150  bool ak8963_read_adjustments(void);
151 
152 protected:
153  Device *_interface;
154 
155  friend class ICM20948;
156 
157  /* Directly measure from the _interface if possible */
158  void measure();
159 
160  /* Update the state with prefetched data (internally called by the regular measure() )*/
161  void _measure(struct ak8963_regs data);
162 
163  uint8_t read_reg(unsigned reg);
164  void write_reg(unsigned reg, uint8_t value);
165 
166  bool is_passthrough() { return _interface == nullptr; }
167 
168 private:
169  ICM20948 *_parent;
170  orb_advert_t _mag_topic;
171  int _mag_orb_class_instance;
172  int _mag_class_instance;
173  bool _mag_reading_data;
174  ringbuffer::RingBuffer *_mag_reports;
175  struct mag_calibration_s _mag_scale;
176  float _mag_range_scale;
177  perf_counter_t _mag_reads;
178  perf_counter_t _mag_errors;
179  perf_counter_t _mag_overruns;
180  perf_counter_t _mag_overflows;
181  perf_counter_t _mag_duplicates;
182  float _mag_asa_x;
183  float _mag_asa_y;
184  float _mag_asa_z;
185 
186  bool check_duplicate(uint8_t *mag_data);
187 
188  // keep last mag reading for duplicate detection
189  uint8_t _last_mag_data[6];
190 
191  /* do not allow to copy this class due to pointer data members */
192  ICM20948_mag(const ICM20948_mag &);
193  ICM20948_mag operator=(const ICM20948_mag &);
194 };
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
Helper class implementing the magnetometer driver node.
Definition: mag.h:132
Abstract class for any character device.
Definition: CDev.hpp:60
Header common to all counters.
Definition: perf_counter.cpp:65
Definition: icm20948.h:377
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
Definition: mag.h:113
Performance measuring tools.