Paparazzi UAS v7.0_unstable
Paparazzi is a free software Unmanned Aircraft System.
Loading...
Searching...
No Matches
ak8975.c
Go to the documentation of this file.
1/*
2 * Copyright (C) 2015 Xavier Paris, Gautier Hattenberger
3 *
4 * This file is part of paparazzi.
5 *
6 * paparazzi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2, or (at your option)
9 * any later version.
10 *
11 * paparazzi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with paparazzi; see the file COPYING. If not, see
18 * <http://www.gnu.org/licenses/>.
19 */
20
28#include "peripherals/ak8975.h"
29#include "mcu_periph/sys_time.h"
30
31#define AK8975_MEAS_TIME_MS 9
32
33// Internal calibration coeff
34// Currently fetched at startup but not used after
35// Only relying on general IMU mag calibration
36static float calibration_values[3] = { 0, 0, 0 };
37
38static float __attribute__((unused)) get_ajusted_value(const int16_t val, const uint8_t axis)
39{
40 const float H = (float) val;
41 const float corr_factor = calibration_values[axis];
42 const float Hadj = corr_factor * H;
43
44 return Hadj;
45}
46
47void ak8975_init(struct Ak8975 *ak, struct i2c_periph *i2c_p, uint8_t addr)
48{
49 /* set i2c_peripheral */
50 ak->i2c_p = i2c_p;
51 /* set i2c address */
52 ak->i2c_trans.slave_addr = addr;
53
55
56 ak->initialized = false;
59 ak->data_available = false;
60}
61
62// Configure
63void ak8975_configure(struct Ak8975 *ak)
64{
65 // Only configure when not busy
67 && ak->i2c_trans.status != I2CTransDone) {
68 return;
69 }
70
71 // Only when succesfull continue with next
72 if (ak->i2c_trans.status == I2CTransSuccess) {
73 ak->init_status++;
74 }
75
77 switch (ak->init_status) {
78
79 case AK_CONF_UNINIT:
80 // Set AK8975 in fuse ROM access mode to read ADC calibration data
83 i2c_transmit(ak->i2c_p, &(ak->i2c_trans), ak->i2c_trans.slave_addr, 2);
84 break;
85
87 // Request AK8975 for ADC calibration data
89 i2c_transceive(ak->i2c_p, &(ak->i2c_trans), ak->i2c_trans.slave_addr, 1, 3);
90 break;
91
93 // Read config
94 for (uint8_t i =0; i<=2; i++)
96 ((((float)(ak->i2c_trans.buf[i]) - 128.0f)*0.5f)/128.0f)+1.0f;
97
98 // Set AK8975 in power-down mode to stop read calibration data
101 i2c_transmit(ak->i2c_p, &(ak->i2c_trans), ak->i2c_trans.slave_addr, 2);
102 break;
103
105 ak->initialized = true;
106 break;
107
108 default:
109 break;
110 }
111}
112
113void ak8975_read(struct Ak8975 *ak)
114{
115 if (ak->status != AK_STATUS_IDLE) {
116 return;
117 }
118
119 // Send single measurement request
122 i2c_transmit(ak->i2c_p, &(ak->i2c_trans), ak->i2c_trans.slave_addr, 2);
125}
126
127// Get raw value
128#define RawFromBuf(_buf,_idx) ((int16_t)(_buf[_idx] | (_buf[_idx+1] << 8)))
129// Raw is actually a 14 bits signed value
130#define Int16FromRaw(_raw) ( (_raw & 0x1FFF) > 0xFFF ? (_raw & 0x1FFF) - 0x2000 : (_raw & 0x0FFF) )
131void ak8975_event(struct Ak8975 *ak)
132{
133 if (!ak->initialized) {
134 return;
135 }
136
137 switch (ak->status) {
138
139 case AK_STATUS_MEAS:
140 // Send a read data command if measurement time is done (9ms max)
141 if (ak->i2c_trans.status == I2CTransSuccess &&
144 i2c_transceive(ak->i2c_p, &(ak->i2c_trans), ak->i2c_trans.slave_addr, 1, 8);
145 ak->status++;
146 }
147 break;
148
149 case AK_STATUS_READ:
150 if (ak->i2c_trans.status == I2CTransSuccess) {
151 // Mag data :
152 // Status 1
153 // 1 byte
154 // Measures :
155 // 2 bytes
156 // 2 bytes
157 // 2 bytes
158 // Status 2
159 // 1 byte
160
161 // Read status and error bytes
162 const bool dr = ak->i2c_trans.buf[0] & 0x01; // data ready
163 const bool de = ak->i2c_trans.buf[7] & 0x04; // data error
164 const bool mo = ak->i2c_trans.buf[7] & 0x08; // mag overflow
165 if (de || !dr) {
166 // read error or data not ready, keep reading
167 break;
168 }
169 if (mo) {
170 // overflow, back to idle
172 }
173 // Copy the data
174 int16_t val;
175 val = RawFromBuf(ak->i2c_trans.buf, 1);
176 ak->data.vect.x = Int16FromRaw(val);
177 val = RawFromBuf(ak->i2c_trans.buf, 3);
178 ak->data.vect.y = Int16FromRaw(val);
179 val = RawFromBuf(ak->i2c_trans.buf, 5);
180 ak->data.vect.z = Int16FromRaw(val);
181 ak->data_available = true;
182 // End reading, back to idle
184 break;
185 }
186 break;
187
188 default:
190 // Goto idle
193 }
194 break;
195 }
196}
197
@ AK_STATUS_IDLE
Definition ak8963.h:47
@ AK_STATUS_READ
Definition ak8963.h:48
@ AK_CONF_UNINIT
Definition ak8963.h:40
void ak8975_read(struct Ak8975 *ak)
Definition ak8975.c:113
void ak8975_configure(struct Ak8975 *ak)
Definition ak8975.c:63
void ak8975_init(struct Ak8975 *ak, struct i2c_periph *i2c_p, uint8_t addr)
Definition ak8975.c:47
#define RawFromBuf(_buf, _idx)
Definition ak8975.c:128
#define Int16FromRaw(_raw)
Definition ak8975.c:130
void ak8975_event(struct Ak8975 *ak)
Definition ak8975.c:131
#define AK8975_MEAS_TIME_MS
Definition ak8975.c:31
static float calibration_values[3]
Definition ak8975.c:36
static float get_ajusted_value(const int16_t val, const uint8_t axis)
Definition ak8975.c:38
Driver for the AKM AK8975 magnetometer.
enum Ak8975Status status
main status
Definition ak8975.h:64
#define AK8975_MODE_FUSE_ACCESS
Definition ak8975.h:39
@ AK_DISABLE_ACCESS_CALIBRATION
Definition ak8975.h:47
@ AK_CONF_REQUESTED
Definition ak8975.h:48
@ AK_REQ_CALIBRATION
Definition ak8975.h:46
struct i2c_transaction i2c_trans
i2c transaction used for communication with the ak8936
Definition ak8975.h:61
enum Ak8975ConfStatus init_status
init status
Definition ak8975.h:65
uint32_t last_meas_time
last measurement time in ms
Definition ak8975.h:66
@ AK_STATUS_MEAS
Definition ak8975.h:54
#define AK8975_REG_CNTL_ADDR
Definition ak8975.h:37
volatile bool data_available
data ready flag
Definition ak8975.h:68
bool initialized
config done flag
Definition ak8975.h:62
struct i2c_periph * i2c_p
peripheral used for communcation
Definition ak8975.h:60
#define AK8975_MODE_SINGLE_MEAS
Definition ak8975.h:41
#define AK8975_REG_ASASX
Definition ak8975.h:38
union Ak8975::@311 data
#define AK8975_REG_ST1_ADDR
Definition ak8975.h:36
#define AK8975_MODE_POWER_DOWN
Definition ak8975.h:40
uint32_t get_sys_time_msec(void)
Get the time in milliseconds since startup.
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition i2c.h:122
enum I2CTransactionStatus status
Transaction status.
Definition i2c.h:126
uint8_t slave_addr
Slave address.
Definition i2c.h:104
bool i2c_transmit(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len)
Submit a write only transaction.
Definition i2c.c:202
bool i2c_transceive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint8_t len_w, uint16_t len_r)
Submit a write/read transaction.
Definition i2c.c:222
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition i2c.h:57
@ I2CTransFailed
transaction failed
Definition i2c.h:58
@ I2CTransDone
transaction set to done by user level
Definition i2c.h:59
static struct FloatVect3 H
uint16_t foo
Definition main_demo5.c:58
Architecture independent timing functions.
uint16_t val[TCOUPLE_NB]
short int16_t
Typedef defining 16 bit short type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.