Paparazzi UAS  v5.18.0_stable
Paparazzi is a free software Unmanned Aircraft System.
lsm303dlhc_i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2011 Gautier Hattenberger <gautier.hattenberger@enac.fr>
3  * 2013 Felix Ruess <felix.ruess@gmail.com>
4  *
5  * This file is part of paparazzi.
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
31 #include "std.h"
32 
39 void lsm303dlhc_i2c_init(struct Lsm303dlhc_i2c *lsm, struct i2c_periph *i2c_p, uint8_t addr)
40 {
41  /* set i2c_peripheral */
42  lsm->i2c_p = i2c_p;
43  /* set i2c address */
44  lsm->i2c_trans.slave_addr = addr;
46  /* set default config options */
47  if (addr == LSM303DLHC_ACC_ADDR) {
49  lsm->init_status.acc = LSM_CONF_ACC_UNINIT;
50  } else {
52  lsm->init_status.mag = LSM_CONF_MAG_UNINIT;
53  }
54  lsm->initialized = false;
55 }
56 
57 static void lsm303dlhc_i2c_tx_reg(struct Lsm303dlhc_I2c *lsm, uint8_t reg, uint8_t val)
58 {
59  lsm->i2c_trans.type = I2CTransTx;
60  lsm->i2c_trans.buf[0] = reg;
61  lsm->i2c_trans.buf[1] = val;
62  lsm->i2c_trans.len_r = 0;
63  lsm->i2c_trans.len_w = 2;
64  i2c_submit(lsm->i2c_p, &(lsm->i2c_trans));
65 }
66 
68 static void lsm303dlhc_i2c_send_config(struct Lsm303dlhc_I2c *lsm)
69 {
70  if (lsm->i2c_trans.slave_addr == LSM303DLHC_ACC_ADDR) {
71  switch (lsm->init_status.acc) {
72  case LSM_CONF_ACC_CTRL_REG4_A:
73  lsm303dlhc_i2c_tx_reg(lsm, LSM303DLHC_REG_CTRL_REG4_A,
74  (lsm->config.acc.scale & LSM303DLHC_FS_MASK) |
75  (lsm->config.acc.hres & LSM303DLHC_DEFAULT_HR));
76  lsm->init_status.acc++;
77  break;
78  case LSM_CONF_ACC_CTRL_REG1_A:
79  lsm303dlhc_i2c_tx_reg(lsm, LSM303DLHC_REG_CTRL_REG1_A,
80  (lsm->config.acc.rate & LSM303DLHC_ODR_MASK) |
81  (lsm->config.acc.lp_mode & LSM303DLHC_LPen) |
83  lsm->init_status.acc++;
84  break;
85  case LSM_CONF_ACC_CTRL_REG3_A:
86  lsm303dlhc_i2c_tx_reg(lsm, LSM303DLHC_REG_CTRL_REG3_A, LSM303DLHC_I1_DRDY1);
87  lsm->init_status.acc++;
88  break;
89  case LSM_CONF_ACC_DONE:
90  lsm->initialized = true;
91  lsm->i2c_trans.status = I2CTransDone;
93  break;
94  default:
95  break;
96  }
97  } else {
98  switch (lsm->init_status.mag) {
99  case LSM_CONF_MAG_CRA_REG_M:
100  lsm303dlhc_i2c_tx_reg(lsm, LSM303DLHC_REG_CRA_REG_M, lsm->config.mag.rate);
101  lsm->init_status.mag++;
102  break;
103  case LSM_CONF_MAG_CRB_REG_M:
104  lsm303dlhc_i2c_tx_reg(lsm, LSM303DLHC_REG_CRB_REG_M, lsm->config.mag.gain);
105  lsm->init_status.mag++;
106  break;
107  case LSM_CONF_MAG_MR_REG_M:
108  lsm303dlhc_i2c_tx_reg(lsm, LSM303DLHC_REG_MR_REG_M, lsm->config.mag.mode);
109  lsm->init_status.mag++;
110  break;
111  case LSM_CONF_MAG_DONE:
112  lsm->initialized = true;
113  lsm->i2c_trans.status = I2CTransDone;
114  break;
115  default:
116  break;
117  }
118  }
119 }
120 
121 // Configure
122 void lsm303dlhc_i2c_start_configure(struct Lsm303dlhc_I2c *lsm)
123 {
124  if (lsm->i2c_trans.slave_addr == LSM303DLHC_ACC_ADDR) {
125  if (lsm->init_status.acc == LSM_CONF_ACC_UNINIT) {
126  lsm->init_status.acc++;
127  if (lsm->i2c_trans.status == I2CTransSuccess || lsm->i2c_trans.status == I2CTransDone) {
128  lsm303dlhc_send_config(lsm);
129  }
130  }
131  } else {
132  if (lsm->init_status.mag == LSM_CONF_MAG_UNINIT) {
133  lsm->init_status.mag++;
134  if (lsm->i2c_trans.status == I2CTransSuccess || lsm->i2c_trans.status == I2CTransDone) {
136  }
137  }
138  }
139 }
140 
141 // Normal reading
142 void lsm303dlhc_i2c_read(struct Lsm303dlhc *lsm)
143 {
144  if (lsm->i2c_trans.slave_addr == LSM303DLHC_ACC_ADDR) {
145  //if ((lsm->init_status.acc == LSM_CONF_ACC_CLR_INT_READ) && (lsm->i2c_trans.status == I2CTransDone)){
146  if (!(lsm->initialized) || (lsm->initialized && lsm->i2c_trans.status == I2CTransDone)) {
147  lsm->i2c_trans.buf[0] = LSM303DLHC_REG_OUT_X_L_A | 0x80;
148  lsm->i2c_trans.type = I2CTransTxRx;
149  lsm->i2c_trans.len_r = 6;
150  lsm->i2c_trans.len_w = 1;
151  i2c_submit(lsm->i2c_p, &(lsm->i2c_trans));
152  }
153  } else {
154  if (lsm->initialized && lsm->i2c_trans.status == I2CTransDone) {
155  lsm->i2c_trans.buf[0] = LSM303DLHC_REG_OUT_X_H_M;
156  lsm->i2c_trans.type = I2CTransTxRx;
157  lsm->i2c_trans.len_r = 6;
158  lsm->i2c_trans.len_w = 1;
159  i2c_submit(lsm->i2c_p, &(lsm->i2c_trans));
160  }
161  }
162 }
163 
164 #define Int16FromBuf(_buf,_idx) ((int16_t)((_buf[_idx+1]<<8) | _buf[_idx]))
165 
166 void lsm303dlhc_i2c_event(struct Lsm303dlhc *lsm)
167 {
168  if (lsm->initialized) {
169  if (lsm->i2c_trans.status == I2CTransFailed) {
170  lsm->i2c_trans.status = I2CTransDone;
171  } else if (lsm->i2c_trans.status == I2CTransSuccess) {
172  lsm->data.vect.x = Int16FromBuf(lsm->i2c_trans.buf, 0);
173  lsm->data.vect.y = Int16FromBuf(lsm->i2c_trans.buf, 2);
174  lsm->data.vect.z = Int16FromBuf(lsm->i2c_trans.buf, 4);
175  lsm->data_available = true;
176  lsm->i2c_trans.status = I2CTransDone;
177  } else {
178  }
179  } else {
180  if (lsm->i2c_trans.slave_addr == LSM303DLHC_ACC_ADDR) {
181  if (lsm->init_status.acc != LSM_CONF_ACC_UNINIT) { // Configuring but not yet initialized
182  if (lsm->i2c_trans.status == I2CTransSuccess || lsm->i2c_trans.status == I2CTransDone) {
183  lsm->i2c_trans.status = I2CTransDone;
184  lsm303dlhc_send_config(lsm);
185  }
186  if (lsm->i2c_trans.status == I2CTransFailed) {
187  lsm->init_status.acc--;
188  lsm->i2c_trans.status = I2CTransDone;
189  lsm303dlhc_send_config(lsm); // Retry config (TODO max retry)
190  }
191  }
192  } else {
193  if (lsm->init_status.mag != LSM_CONF_MAG_UNINIT) { // Configuring but not yet initialized
194  if (lsm->i2c_trans.status == I2CTransSuccess || lsm->i2c_trans.status == I2CTransDone) {
195  lsm->i2c_trans.status = I2CTransDone;
196  lsm303dlhc_send_config(lsm);
197  }
198  if (lsm->i2c_trans.status == I2CTransFailed) {
199  lsm->init_status.mag--;
200  lsm->i2c_trans.status = I2CTransDone;
201  lsm303dlhc_send_config(lsm); // Retry config (TODO max retry)
202  }
203  }
204  }
205  }
206 }
lsm303dlhc_i2c_event
void lsm303dlhc_i2c_event(struct Lsm303dlhc *lsm)
Definition: lsm303dlhc_i2c.c:166
val
uint16_t val[TCOUPLE_NB]
Definition: temp_tcouple_adc.c:49
Lsm303dlhc_i2c::i2c_trans
struct i2c_transaction i2c_trans
Definition: lsm303dlhc_i2c.h:43
I2CTransTx
@ I2CTransTx
transmit only transaction
Definition: i2c.h:47
lsm303dlhc_i2c_start_configure
void lsm303dlhc_i2c_start_configure(struct Lsm303dlhc_I2c *lsm)
Definition: lsm303dlhc_i2c.c:122
I2CTransFailed
@ I2CTransFailed
transaction failed
Definition: i2c.h:58
LSM303DLHC_Yen
#define LSM303DLHC_Yen
Definition: lsm303dlhc_regs.h:107
I2CTransSuccess
@ I2CTransSuccess
transaction successfully finished by I2C driver
Definition: i2c.h:57
lsm303dlhc_i2c_tx_reg
static void lsm303dlhc_i2c_tx_reg(struct Lsm303dlhc_I2c *lsm, uint8_t reg, uint8_t val)
Definition: lsm303dlhc_i2c.c:57
std.h
Int16FromBuf
#define Int16FromBuf(_buf, _idx)
Definition: lsm303dlhc_i2c.c:164
LSM303DLHC_Xen
#define LSM303DLHC_Xen
Definition: lsm303dlhc_regs.h:106
lsm303dlhc_i2c_send_config
static void lsm303dlhc_i2c_send_config(struct Lsm303dlhc_I2c *lsm)
Configuration function called once before normal use.
Definition: lsm303dlhc_i2c.c:68
uint8_t
unsigned char uint8_t
Definition: types.h:14
i2c_transaction::status
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
lsm303dlhc_i2c.h
lsm303dlhc_i2c_init
void lsm303dlhc_i2c_init(struct Lsm303dlhc_i2c *lsm, struct i2c_periph *i2c_p, uint8_t addr)
Initialize Lsm303dlhc struct and set default config options.
Definition: lsm303dlhc_i2c.c:39
lsm303dlhc_i2c_read
void lsm303dlhc_i2c_read(struct Lsm303dlhc *lsm)
Definition: lsm303dlhc_i2c.c:142
I2CTransTxRx
@ I2CTransTxRx
transmit and receive transaction
Definition: i2c.h:49
i2c_transaction::slave_addr
uint8_t slave_addr
Slave address.
Definition: i2c.h:104
LSM303DLHC_REG_OUT_X_H_M
#define LSM303DLHC_REG_OUT_X_H_M
Definition: lsm303dlhc_regs.h:42
Lsm303dlhc_i2c::init_status
union Lsm303dlhc_i2c::@326 init_status
LSM303DLHC_REG_OUT_X_L_A
#define LSM303DLHC_REG_OUT_X_L_A
Definition: lsm303dlhc_regs.h:73
lsm303dlhc_acc_set_default_config
static void lsm303dlhc_acc_set_default_config(struct Lsm303dlhcAccConfig *c)
Definition: lsm303dlhc.h:86
LSM303DLHC_ACC_ADDR
#define LSM303DLHC_ACC_ADDR
Definition: lsm303dlhc_regs.h:31
LSM303DLHC_FS_MASK
#define LSM303DLHC_FS_MASK
Definition: lsm303dlhc_regs.h:115
LSM303DLHC_Zen
#define LSM303DLHC_Zen
Definition: lsm303dlhc_regs.h:108
Lsm303dlhc_i2c
Definition: lsm303dlhc_i2c.h:41
Lsm303dlhc_i2c::initialized
bool initialized
config done flag
Definition: lsm303dlhc_i2c.h:44
I2CTransDone
@ I2CTransDone
transaction set to done by user level
Definition: i2c.h:59
i2c_submit
static bool i2c_submit(struct i2c_periph *p, struct i2c_transaction *t)
Submit a I2C transaction.
Definition: i2c.h:266
lsm303dlhc_mag_set_default_config
static void lsm303dlhc_mag_set_default_config(struct Lsm303dlhcMagConfig *c)
Definition: lsm303dlhc.h:92
i2c_periph
Definition: i2c.h:144
Lsm303dlhc_i2c::i2c_p
struct i2c_periph * i2c_p
Definition: lsm303dlhc_i2c.h:42
Lsm303dlhc_i2c::config
union Lsm303dlhc_i2c::@328 config