Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
mpu9250_i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Gautier Hattenberger <gautier.hattenberger@enac.fr>
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 
29 
30 bool imu_mpu9250_configure_mag_slave(Mpu9250ConfigSet mpu_set __attribute__((unused)),
31  void *mpu __attribute__((unused)));
32 
33 void mpu9250_i2c_init(struct Mpu9250_I2c *mpu, struct i2c_periph *i2c_p, uint8_t addr)
34 {
35  /* set i2c_peripheral */
36  mpu->i2c_p = i2c_p;
37 
38  /* slave address */
39  mpu->i2c_trans.slave_addr = addr;
40  /* set inital status: Success or Done */
42 
43  /* set default MPU9250 config options */
45 
46  mpu->data_available = false;
47  mpu->config.initialized = false;
49 
50  /* "internal" ak8963 magnetometer */
51  ak8963_init(&mpu->akm, i2c_p, MPU9250_MAG_ADDR);
52  /* mag is declared as slave to call the configure function,
53  * regardless if it is an actual MPU slave or passthrough
54  */
55  mpu->config.nb_slaves = 1;
56  /* set callback function to configure mag */
58  /* read the mag directly for now */
59  mpu->config.i2c_bypass = true;
60 
62 }
63 
64 
65 static void mpu9250_i2c_write_to_reg(void *mpu, uint8_t _reg, uint8_t _val)
66 {
67  struct Mpu9250_I2c *mpu_i2c = (struct Mpu9250_I2c *)(mpu);
68  mpu_i2c->i2c_trans.buf[0] = _reg;
69  mpu_i2c->i2c_trans.buf[1] = _val;
70  i2c_transmit(mpu_i2c->i2c_p, &(mpu_i2c->i2c_trans), mpu_i2c->i2c_trans.slave_addr, 2);
71 }
72 
73 // Configuration function called once before normal use
75 {
77  mpu->config.init_status++;
80  }
81  }
82 }
83 
84 void mpu9250_i2c_read(struct Mpu9250_I2c *mpu)
85 {
86  if (mpu->config.initialized && mpu->i2c_trans.status == I2CTransDone) {
87  /* set read bit and multiple byte bit, then address */
89  i2c_transceive(mpu->i2c_p, &(mpu->i2c_trans), mpu->i2c_trans.slave_addr, 1, mpu->config.nb_bytes);
90  /* read mag */
91 #ifdef MPU9250_MAG_PRESCALER
92  RunOnceEvery(MPU9250_MAG_PRESCALER, ak8963_read(&mpu->akm));
93 #else
94  ak8963_read(&mpu->akm);
95 #endif
96  }
97 }
98 
99 #define Int16FromBuf(_buf,_idx) ((int16_t)((_buf[_idx]<<8) | _buf[_idx+1]))
100 
102 {
103  if (mpu->config.initialized) {
104  if (mpu->i2c_trans.status == I2CTransFailed) {
106  } else if (mpu->i2c_trans.status == I2CTransSuccess) {
107  // Successfull reading
108  if (bit_is_set(mpu->i2c_trans.buf[0], 0)) {
109  // new data
110  mpu->data_accel.vect.x = Int16FromBuf(mpu->i2c_trans.buf, 1);
111  mpu->data_accel.vect.y = Int16FromBuf(mpu->i2c_trans.buf, 3);
112  mpu->data_accel.vect.z = Int16FromBuf(mpu->i2c_trans.buf, 5);
113  mpu->data_rates.rates.p = Int16FromBuf(mpu->i2c_trans.buf, 9);
114  mpu->data_rates.rates.q = Int16FromBuf(mpu->i2c_trans.buf, 11);
115  mpu->data_rates.rates.r = Int16FromBuf(mpu->i2c_trans.buf, 13);
116 
117  // if we are reading slaves through the mpu, copy the ext_sens_data
118  if ((mpu->config.i2c_bypass == FALSE) && (mpu->config.nb_slaves > 0)) {
119  /* the buffer is volatile, since filled from ISR
120  * but we know it's ok to use it here so we silence the warning
121  */
122 #pragma GCC diagnostic push
123 #pragma GCC diagnostic ignored "-Wcast-qual"
124  memcpy(mpu->data_ext, (uint8_t *) & (mpu->i2c_trans.buf[15]), mpu->config.nb_bytes - 15);
125 #pragma GCC diagnostic pop
126  }
127 
128  mpu->data_available = true;
129  }
131  }
132  } else if (mpu->config.init_status != MPU9250_CONF_UNINIT) { // Configuring but not yet initialized
133  switch (mpu->i2c_trans.status) {
134  case I2CTransFailed:
135  mpu->config.init_status--; // Retry config (TODO max retry)
136  case I2CTransSuccess:
137  case I2CTransDone:
138  mpu9250_send_config(mpu9250_i2c_write_to_reg, (void *)mpu, &(mpu->config));
139  if (mpu->config.initialized) {
141  }
142  break;
143  default:
144  break;
145  }
146  }
147  // Ak8963 event function
148  ak8963_event(&mpu->akm);
149 }
150 
154 bool imu_mpu9250_configure_mag_slave(Mpu9250ConfigSet mpu_set __attribute__((unused)), void *mpu)
155 {
156  struct Mpu9250_I2c *mpu_i2c = (struct Mpu9250_I2c *)(mpu);
157 
158  ak8963_configure(&mpu_i2c->akm);
159  if (mpu_i2c->akm.initialized) {
160  return true;
161  } else {
162  return false;
163  }
164 }
165 
168 {
169  struct Mpu9250_I2c *mpu_i2c = (struct Mpu9250_I2c *)(mpu);
170 
171  if (mpu_i2c->slave_init_status == MPU9250_I2C_CONF_UNINIT) {
172  mpu_i2c->slave_init_status++;
173  }
174 
175  switch (mpu_i2c->slave_init_status) {
177  mpu_set(mpu, MPU9250_REG_USER_CTRL, 0);
178  mpu_i2c->slave_init_status++;
179  break;
181  /* switch to I2C passthrough */
182  mpu_set(mpu, MPU9250_REG_INT_PIN_CFG, (1 << 1));
183  mpu_i2c->slave_init_status++;
184  break;
186  /* configure each slave until all nb_slaves are done */
187  if (mpu_i2c->config.nb_slave_init < mpu_i2c->config.nb_slaves && mpu_i2c->config.nb_slave_init < MPU9250_I2C_NB_SLAVES) {
188  // proceed to next slave if configure for current one returns true
189  if (mpu_i2c->config.slaves[mpu_i2c->config.nb_slave_init].configure(mpu_set, mpu)) {
190  mpu_i2c->config.nb_slave_init++;
191  }
192  }
193  else {
194  /* all slave devies configured, continue MPU side configuration of I2C slave stuff */
195  mpu_i2c->slave_init_status++;
196  }
197  break;
199  if (mpu_i2c->config.i2c_bypass) {
200  /* if bypassing I2C skip MPU I2C master setup */
202  } else {
203  /* disable I2C passthrough again */
204  mpu_set(mpu, MPU9250_REG_INT_PIN_CFG, (0 << 1));
205  mpu_i2c->slave_init_status++;
206  }
207  break;
209  /* configure MPU I2C master clock and stop/start between slave reads */
210  mpu_set(mpu, MPU9250_REG_I2C_MST_CTRL,
211  ((1 << 4) | mpu_i2c->config.i2c_mst_clk));
212  mpu_i2c->slave_init_status++;
213  break;
215  /* Set I2C slaves delayed sample rate */
216  mpu_set(mpu, MPU9250_REG_I2C_MST_DELAY, mpu_i2c->config.i2c_mst_delay);
217  mpu_i2c->slave_init_status++;
218  break;
220  /* I2C slave0 sample rate/2 = 100/2 = 50Hz */
221  mpu_set(mpu, MPU9250_REG_I2C_SLV4_CTRL, 0);
222  mpu_i2c->slave_init_status++;
223  break;
225  /* enable internal I2C master */
226  mpu_set(mpu, MPU9250_REG_USER_CTRL, (1 << MPU9250_I2C_MST_EN));
227  mpu_i2c->slave_init_status++;
228  break;
230  return true;
231  default:
232  break;
233  }
234  return false;
235 }
enum Mpu9250MstClk i2c_mst_clk
MPU I2C master clock speed.
Definition: mpu9250.h:146
Mpu9250I2cSlaveConfigure configure
Definition: mpu9250.h:123
#define MPU9250_MAG_ADDR
Definition: mpu9250_regs.h:35
struct i2c_transaction i2c_trans
Definition: mpu9250_i2c.h:57
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition: i2c.h:122
#define MPU9250_REG_INT_STATUS
Definition: mpu9250_regs.h:93
union Mpu9250_I2c::@318 data_rates
transaction successfully finished by I2C driver
Definition: i2c.h:57
struct Mpu9250Config config
Definition: mpu9250_i2c.h:68
volatile bool data_available
data ready flag
Definition: mpu9250_i2c.h:58
enum Mpu9250ConfStatus init_status
init status
Definition: mpu9250.h:135
uint8_t nb_bytes
number of bytes to read starting with MPU9250_REG_INT_STATUS
Definition: mpu9250.h:134
static void mpu9250_i2c_write_to_reg(void *mpu, uint8_t _reg, uint8_t _val)
Definition: mpu9250_i2c.c:65
bool imu_mpu9250_configure_mag_slave(Mpu9250ConfigSet mpu_set, void *mpu)
callback function to configure ak8963 mag
Definition: mpu9250_i2c.c:154
void mpu9250_i2c_init(struct Mpu9250_I2c *mpu, struct i2c_periph *i2c_p, uint8_t addr)
Definition: mpu9250_i2c.c:33
union Mpu9250_I2c::@317 data_accel
bool mpu9250_configure_i2c_slaves(Mpu9250ConfigSet mpu_set, void *mpu)
configure the registered I2C slaves
Definition: mpu9250_i2c.c:167
uint8_t data_ext[MPU9250_BUFFER_EXT_LEN]
Definition: mpu9250_i2c.h:67
void ak8963_init(struct Ak8963 *ak, struct i2c_periph *i2c_p, uint8_t addr)
Initialize AK8963 struct.
Definition: ak8963.c:34
void mpu9250_i2c_start_configure(struct Mpu9250_I2c *mpu)
Definition: mpu9250_i2c.c:74
bool initialized
config done flag
Definition: ak8963.h:56
void mpu9250_i2c_event(struct Mpu9250_I2c *mpu)
Definition: mpu9250_i2c.c:101
#define FALSE
Definition: std.h:5
bool i2c_bypass
Bypass MPU I2C.
Definition: mpu9250.h:141
void ak8963_read(struct Ak8963 *ak)
Definition: ak8963.c:83
struct Ak8963 akm
"internal" magnetometer
Definition: mpu9250_i2c.h:70
transaction set to done by user level
Definition: i2c.h:59
void mpu9250_send_config(Mpu9250ConfigSet mpu_set, void *mpu, struct Mpu9250Config *config)
Configuration sequence called once before normal use.
Definition: mpu9250.c:81
#define MPU9250_REG_I2C_MST_CTRL
Definition: mpu9250_regs.h:60
void(* Mpu9250ConfigSet)(void *mpu, uint8_t _reg, uint8_t _val)
Configuration function prototype.
Definition: mpu9250.h:117
transaction failed
Definition: i2c.h:58
void mpu9250_set_default_config(struct Mpu9250Config *c)
Definition: mpu9250.c:60
#define MPU9250_REG_I2C_SLV4_CTRL
Definition: mpu9250_regs.h:87
uint8_t nb_slaves
number of used I2C slaves
Definition: mpu9250.h:143
enum Mpu9250I2cSlaveInitStatus slave_init_status
Definition: mpu9250_i2c.h:69
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:278
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
void mpu9250_i2c_read(struct Mpu9250_I2c *mpu)
Definition: mpu9250_i2c.c:84
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:258
#define MPU9250_REG_I2C_MST_DELAY
Definition: mpu9250_regs.h:62
uint8_t slave_addr
Slave address.
Definition: i2c.h:104
I2C peripheral structure.
Definition: i2c.h:138
void ak8963_event(struct Ak8963 *ak)
Definition: ak8963.c:95
#define MPU9250_REG_USER_CTRL
Definition: mpu9250_regs.h:41
unsigned char uint8_t
Definition: types.h:14
#define MPU9250_I2C_MST_EN
Definition: mpu9250_regs.h:131
struct Mpu9250I2cSlave slaves[MPU9250_I2C_NB_SLAVES]
I2C slaves.
Definition: mpu9250.h:145
#define MPU9250_REG_INT_PIN_CFG
Definition: mpu9250_regs.h:91
#define Int16FromBuf(_buf, _idx)
Definition: mpu9250_i2c.c:99
uint8_t nb_slave_init
number of already configured/initialized slaves
Definition: mpu9250.h:144
void ak8963_configure(struct Ak8963 *ak)
Definition: ak8963.c:46
#define MPU9250_I2C_NB_SLAVES
Definition: mpu9250.h:52
bool initialized
config done flag
Definition: mpu9250.h:136
struct i2c_periph * i2c_p
Definition: mpu9250_i2c.h:56
Driver for the MPU-9250 using I2C.
uint8_t i2c_mst_delay
MPU I2C slaves delayed sample rate.
Definition: mpu9250.h:147