Paparazzi UAS  v5.10_stable-5-g83a0da5-dirty
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
lsm303dlhc_spi.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 
30 #include "std.h"
31 
32 void lsm303dlhc_spi_init(struct Lsm303dlhc_Spi *lsm, struct spi_periph *spi_p, uint8_t slave_idx,
34 {
35  /* set spi_peripheral */
36  lsm->spi_p = spi_p;
37 
38  /* set internal target mag/acc*/
39  lsm->target = target;
40 
41  /* configure spi transaction */
44  lsm->spi_trans.dss = SPIDss8bit;
46  lsm->spi_trans.cdiv = SPIDiv64;
47 
49  lsm->spi_trans.slave_idx = slave_idx;
50  lsm->spi_trans.output_length = 2;
51  lsm->spi_trans.input_length = 8;
52  // callback currently unused
53  lsm->spi_trans.before_cb = NULL;
54  lsm->spi_trans.after_cb = NULL;
55  lsm->spi_trans.input_buf = &(lsm->rx_buf[0]);
56  lsm->spi_trans.output_buf = &(lsm->tx_buf[0]);
57 
58  /* set inital status: Success or Done */
60 
61  /* set default LSM303D config options */
65 
66  lsm->initialized = FALSE;
69 }
70 
71 static void lsm303dlhc_spi_tx_reg(struct Lsm303dlhc_Spi *lsm, uint8_t reg, uint8_t val)
72 {
73  lsm->spi_trans.output_length = 2;
74  lsm->spi_trans.input_length = 0;
75  lsm->tx_buf[0] = reg;
76  lsm->tx_buf[1] = val;
77  spi_submit(lsm->spi_p, &(lsm->spi_trans));
78 }
79 
82 {
83  if (lsm->target ==
84  LSM_TARGET_ACC) { // the complete config done below currently is one shot for both acc and mag. So, only do it for one of the devices.
85  switch (lsm->init_status) {
86  case LSM_CONF_WHO_AM_I:
87  /* query device id */
88  lsm->spi_trans.output_length = 1;
89  lsm->spi_trans.input_length = 2;
90  /* set read bit then reg address */
91  lsm->tx_buf[0] = (1 << 7 | LSM303DLHC_REG_WHO_AM_I);
92  if (spi_submit(lsm->spi_p, &(lsm->spi_trans))) {
93  if (lsm->rx_buf[1] == LSM303DLHC_WHO_I_AM) {
94  lsm->init_status++;
95  }
96  }
97  break;
98  case LSM_CONF_CTRL_REG1:
100  (lsm->config.acc.rate & LSM303DLHC_AODR_MASK) |
102  lsm->init_status++;
103  break;
104  case LSM_CONF_CTRL_REG2:
106  lsm->init_status++;
107  break;
108  case LSM_CONF_CTRL_REG3:
110  lsm->init_status++;
111  break;
112  case LSM_CONF_CTRL_REG4:
114  lsm->init_status++;
115  return;
116  break;
117  case LSM_CONF_CTRL_REG5:
119  (lsm->config.mag.rate & LSM303DLHC_M_ODR_MASK));
120  lsm->init_status++;
121  return;
122  break;
123  case LSM_CONF_CTRL_REG6:
125  (lsm->config.mag.scale & LSM303DLHC_MFS_MASK));
126  lsm->init_status++;
127  break;
128  case LSM_CONF_CTRL_REG7:
130  lsm->init_status++;
131  break;
132  case LSM_CONF_DONE:
133  lsm->initialized = TRUE;
135  return;
136  break;
137  default:
138  break;
139  }
140  } else {
141  lsm->initialized = TRUE;
143  }
144 }
145 
146 // Configure
148 {
149  if (lsm->init_status == LSM_CONF_UNINIT) {
150  lsm->init_status++;
151  if (lsm->spi_trans.status == SPITransSuccess || lsm->spi_trans.status == SPITransDone) {
153  }
154  }
155 }
156 
157 // Normal reading
159 {
160  if (lsm->target == LSM_TARGET_ACC) {
161  if (!(lsm->initialized) || (lsm->initialized && lsm->spi_trans.status == SPITransDone)) {
162  lsm->spi_trans.output_length = 1;
163  lsm->spi_trans.input_length = 8;
164  /* set read bit and multiple byte bit, then address */
165  lsm->tx_buf[0] = LSM303DLHC_REG_STATUS_REG_A | 1 << 7 | 1 << 6;
166  spi_submit(lsm->spi_p, &(lsm->spi_trans));
167  }
168  } else {
169  if (lsm->initialized && lsm->spi_trans.status == SPITransDone) {
170  lsm->spi_trans.output_length = 1;
171  lsm->spi_trans.input_length = 8;
172  /* set read bit and multiple byte bit, then address */
173  lsm->tx_buf[0] = LSM303DLHC_REG_STATUS_REG_M | 1 << 7 | 1 << 6;
174  spi_submit(lsm->spi_p, &(lsm->spi_trans));
175  }
176  }
177 }
178 
179 #define Int16FromBuf(_buf,_idx) ((int16_t)((_buf[_idx+1]<<8) | _buf[_idx]))
180 
182 {
183  if (lsm->initialized) {
184  if (lsm->spi_trans.status == SPITransFailed) {
186  } else if (lsm->spi_trans.status == SPITransSuccess) {
187  if (lsm->target == LSM_TARGET_ACC) {
188  if (!(lsm->rx_buf[1] & LSM303DLHC_REG_STATUS_ZYXADA)) {
190  return;
191  }
192  lsm->data_accel.vect.x = Int16FromBuf(lsm->rx_buf, 2);
193  lsm->data_accel.vect.y = Int16FromBuf(lsm->rx_buf, 4);
194  lsm->data_accel.vect.z = Int16FromBuf(lsm->rx_buf, 6);
195  lsm->data_available_acc = TRUE;
197  } else { //magneto
198  if (!(lsm->rx_buf[1] & LSM303DLHC_REG_STATUS_ZYXMDA)) {
200  return;
201  }
202  lsm->data_mag.vect.x = Int16FromBuf(lsm->rx_buf, 2);
203  lsm->data_mag.vect.y = Int16FromBuf(lsm->rx_buf, 4);
204  lsm->data_mag.vect.z = Int16FromBuf(lsm->rx_buf, 6);
205  lsm->data_available_mag = TRUE;
207  }
208  }
209  } else {
210  if (lsm->init_status != LSM_CONF_UNINIT) { // Configuring but not yet initialized
211  if (lsm->spi_trans.status == SPITransSuccess || lsm->spi_trans.status == SPITransDone) {
214  }
215  if (lsm->spi_trans.status == SPITransFailed) {
216  lsm->init_status--;
218  lsm303dlhc_spi_send_config(lsm); // Retry config (TODO max retry)
219  }
220  }
221  }
222 }
void lsm303dlhc_spi_event(struct Lsm303dlhc_Spi *lsm)
enum SPIClockPolarity cpol
clock polarity control
Definition: spi.h:149
#define LSM303DLHC_FS_MASK
#define LSM303DLHC_WHO_I_AM
#define LSM303DLHC_REG_CTRL3
#define LSM303DLHC_Yen
enum SPIClockDiv cdiv
prescaler of main clock to use as SPI clock
Definition: spi.h:153
#define LSM303DLHC_M_ODR_MASK
uint16_t output_length
number of data words to write
Definition: spi.h:146
#define LSM303DLHC_AHPM_MASK
#define LSM303DLHC_REG_STATUS_REG_M
struct spi_periph * spi_p
#define LSM303DLHC_I1_DRDY_A
CPHA = 1.
Definition: spi.h:69
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
Definition: spi_arch.c:364
CPOL = 1.
Definition: spi.h:78
enum SPIBitOrder bitorder
MSB/LSB order.
Definition: spi.h:152
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
Definition: spi.h:144
static void lsm303dlhc_acc_set_default_config(struct Lsm303dlhcAccConfig *c)
Definition: lsm303dlhc.h:86
#define LSM303DLHC_REG_WHO_AM_I
enum SPISlaveSelect select
slave selection behavior
Definition: spi.h:148
volatile uint8_t rx_buf[8]
#define FALSE
Definition: std.h:5
enum SPIClockPhase cpha
clock phase control
Definition: spi.h:150
volatile bool data_available_acc
data ready flag accelero
#define TRUE
Definition: std.h:4
SPI peripheral structure.
Definition: spi.h:168
void lsm303dlhc_spi_start_configure(struct Lsm303dlhc_Spi *lsm)
Definition: spi.h:84
#define LSM303DLHC_REG_CTRL7
union Lsm303dlhc_Spi::@310 data_mag
volatile uint8_t tx_buf[2]
union Lsm303dlhc_Spi::@311 config
#define LSM303DLHC_MFS_MASK
SPICallback after_cb
NULL or function called after the transaction.
Definition: spi.h:155
#define Int16FromBuf(_buf, _idx)
uint16_t val[TCOUPLE_NB]
union Lsm303dlhc_Spi::@309 data_accel
#define LSM303DLHC_REG_STATUS_REG_A
#define LSM303DLHC_AODR_MASK
#define LSM303DLHC_REG_CTRL1
#define LSM303DLHC_REG_CTRL4
struct spi_transaction spi_trans
#define LSM303DLHC_REG_CTRL5
enum Lsm303dlhcTarget target
uint16_t input_length
number of data words to read
Definition: spi.h:145
bool initialized
config done flag
static void lsm303dlhc_mag_set_default_config(struct Lsm303dlhcMagConfig *c)
Definition: lsm303dlhc.h:92
unsigned char uint8_t
Definition: types.h:14
volatile bool data_available_mag
data ready flag magneto
#define LSM303DLHC_Zen
void lsm303dlhc_spi_read(struct Lsm303dlhc_Spi *lsm)
#define LSM303DLHC_REG_STATUS_ZYXMDA
static void lsm303dlhc_spi_send_config(struct Lsm303dlhc_Spi *lsm)
Configuration function called once before normal use.
#define LSM303DLHC_REG_CTRL6
slave is selected before transaction and unselected after
Definition: spi.h:57
#define LSM303DLHC_REG_STATUS_ZYXADA
enum SPIDataSizeSelect dss
data transfer word size
Definition: spi.h:151
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
Definition: spi.h:147
Definition: spi.h:119
volatile uint8_t * input_buf
pointer to receive buffer for DMA
Definition: spi.h:143
void lsm303dlhc_spi_init(struct Lsm303dlhc_Spi *lsm, struct spi_periph *spi_p, uint8_t slave_idx, enum Lsm303dlhcTarget target)
enum Lsm303dlhcConfStatus init_status
SPICallback before_cb
NULL or function called before the transaction.
Definition: spi.h:154
struct FloatVect2 target
static void lsm303dlhc_spi_tx_reg(struct Lsm303dlhc_Spi *lsm, uint8_t reg, uint8_t val)
#define LSM303DLHC_REG_CTRL2
#define LSM303DLHC_Xen
Lsm303dlhcTarget
Definition: lsm303dlhc.h:81
enum SPITransactionStatus status
Definition: spi.h:156
#define LSM303DLHC_I2_DRDY_M