Firmware
ak09916.hpp
1 /****************************************************************************
2  *
3  * Copyright (c) 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 #pragma once
35 
36 
37 #include <px4_config.h>
38 
39 #include <sys/types.h>
40 #include <stdint.h>
41 #include <stdbool.h>
42 #include <stddef.h>
43 #include <stdlib.h>
44 #include <semaphore.h>
45 #include <string.h>
46 #include <fcntl.h>
47 #include <poll.h>
48 #include <errno.h>
49 #include <stdio.h>
50 #include <math.h>
51 #include <unistd.h>
52 #include <px4_log.h>
53 
54 #include <perf/perf_counter.h>
55 #include <systemlib/err.h>
56 #include <nuttx/wqueue.h>
57 #include <systemlib/conversions.h>
58 
59 #include <nuttx/arch.h>
60 #include <nuttx/clock.h>
61 
62 #include <board_config.h>
63 #include <drivers/drv_hrt.h>
64 
67 #include <drivers/device/i2c.h>
68 #include <drivers/drv_mag.h>
69 
70 
71 #define AK09916_SAMPLE_RATE 100
72 #define AK09916_DEVICE_PATH_MAG "/dev/ak09916_i2c_int"
73 
74 #define AK09916_DEVICE_PATH_MAG_EXT "/dev/ak09916_i2c_ext"
75 
76 /* in 16-bit sampling mode the mag resolution is 1.5 milli Gauss per bit */
77 
78 #define AK09916_MAG_RANGE_GA 1.5e-3f;
79 
80 /* ak09916 deviating register addresses and bit definitions */
81 #define AK09916_I2C_ADDR 0x0C
82 
83 #define AK09916_DEVICE_ID_A 0x48
84 #define AK09916_DEVICE_ID_B 0x09 // additional ID byte ("INFO" on AK9063 without content specification.)
85 
86 #define AK09916REG_WIA 0x00
87 
88 #define AK09916REG_HXL 0x11
89 #define AK09916REG_HXH 0x12
90 #define AK09916REG_HYL 0x13
91 #define AK09916REG_HYH 0x14
92 #define AK09916REG_HZL 0x15
93 #define AK09916REG_HZH 0x16
94 #define AK09916REG_ST1 0x10
95 #define AK09916REG_ST2 0x18
96 #define AK09916REG_CNTL2 0x31
97 #define AK09916REG_CNTL3 0x32
98 
99 
100 #define AK09916_CNTL2_POWERDOWN_MODE 0x00
101 #define AK09916_RESET 0x01
102 #define AK09916_CNTL2_SINGLE_MODE 0x01 /* default */
103 #define AK09916_CNTL2_CONTINOUS_MODE_10HZ 0x02
104 #define AK09916_CNTL2_CONTINOUS_MODE_20HZ 0x04
105 #define AK09916_CNTL2_CONTINOUS_MODE_50HZ 0x06
106 #define AK09916_CNTL2_CONTINOUS_MODE_100HZ 0x08
107 #define AK09916_CNTL2_SELFTEST_MODE 0x10
108 #define AK09916_CNTL3_SRST 0x01
109 #define AK09916_ST1_DRDY 0x01
110 #define AK09916_ST1_DOR 0x02
111 
112 
113 #pragma pack(push, 1)
114 struct ak09916_regs {
115  uint8_t st1;
116  int16_t x;
117  int16_t y;
118  int16_t z;
119  uint8_t tmps;
120  uint8_t st2;
121 };
122 #pragma pack(pop)
123 
124 
125 
129 class AK09916 : public device::I2C
130 {
131 public:
132  AK09916(int bus, const char *path, enum Rotation rotation);
133  ~AK09916();
134 
135  virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
136  virtual int init();
137  virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
138 
139  void read_block(uint8_t reg, uint8_t *val, uint8_t count);
140 
141  int reset(void);
142  int probe(void);
143  int setup(void);
144  void print_info(void);
145  int setup_master_i2c(void);
146  bool check_id(uint8_t &id);
147 
148 
149  static void cycle_trampoline(void *arg);
150  void start(void);
151  void stop(void);
152  void cycle(void);
153 
154 protected:
155 
156  friend class ICM20948;
157 
158  /* Directly measure from the _interface if possible */
159  void measure();
160 
161  /* Update the state with prefetched data (internally called by the regular measure() )*/
162  void _measure(struct ak09916_regs data);
163 
164  uint8_t read_reg(uint8_t reg);
165  void write_reg(uint8_t reg, uint8_t value);
166 
167 private:
168  work_s _work{};
169  unsigned _measure_ticks;
170 
171  enum Rotation _rotation;
172  orb_advert_t _mag_topic;
173  int _mag_orb_class_instance;
174  int _mag_class_instance;
175  bool _mag_reading_data;
176  ringbuffer::RingBuffer *_mag_reports;
177  mag_report _last_report {};
178  struct mag_calibration_s _mag_scale;
179  float _mag_range_scale;
180  perf_counter_t _mag_reads;
181  perf_counter_t _mag_errors;
182  perf_counter_t _mag_overruns;
183  perf_counter_t _mag_overflows;
184  perf_counter_t _mag_duplicates;
185  float _mag_asa_x;
186  float _mag_asa_y;
187  float _mag_asa_z;
188 
189  bool check_duplicate(uint8_t *mag_data);
190 
191  // keep last mag reading for duplicate detection
192  uint8_t _last_mag_data[6];
193 
194  /* do not allow to copy this class due to pointer data members */
195  AK09916(const AK09916 &);
196  AK09916 operator=(const AK09916 &);
197 };
A flexible ringbuffer class.
Configuration flags used in code.
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
High-resolution timer with callouts and timekeeping.
Helper class implementing the magnetometer driver node.
Definition: ak09916.hpp:129
Header common to all counters.
Definition: perf_counter.cpp:65
Definition of commonly used conversions.
Definition: icm20948.h:377
void reset(enum BMP280_BUS busid)
Reset the driver.
Definition: bmp280.cpp:743
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
Platform dependant logging/debug implementation.
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
Definition: mag.h:113
A resettable integrator.
Definition: video_device.h:50
Performance measuring tools.