KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
lsm303agr.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  * ----------------------
4  *
5  * Copyright 2012-2016 KM3NeT Collaboration
6  *
7  * All Rights Reserved.
8  *
9  *
10  * File : lsm303.c
11  * Created : 24 mrt. 2016
12  * Author : Vincent van Beveren
13  */
14 
15 #include "drv/i2c/lsm303agr.h"
16 
17 #include <stdio.h>
18 
19 // LSM303AGR Addresses. Why 2!?
20 #define _ACC_ADDR 0x19 // For registers 00 - 3F
21 #define _MAG_ADDR 0x1E // For registers 40 - 6F
22 
23 #define _MASK_VAL(PREFIX, VAL) ( ( PREFIX ## _MASK ) & ( ( VAL ) << ( PREFIX ## _SHIFT ) ) )
24 
25 // Marks auto-increment mode
26 #define _AUTO_INC_REG 0x80
27 
28 
29 
30 
31 #define _REG_AUX_A 0x07
32 #define _REG_AUX_A_TOR 0x40 // Temperature overrun
33 #define _REG_AUX_A_TDA 0x04 // Temperature data available.
34 
35 // Temperature registers
36 #define _REG_TEMP_OUT_L 0x0C
37 #define _REG_TEMP_OUT_H 0x0D
38 
39 
40 // Accellerometer ID
41 #define _REG_WHO_AM_I_A 0x0F
42 #define _REG_WHO_AM_I_A_ID 0x33
43 
44 
45 #define _REG_TEMP_CFG 0x1F
46 #define _REG_TEMP_CFG_DISABLE 0x00
47 #define _REG_TEMP_CFG_ENABLE 0xC0
48 
49 
50 
51 #define _REG_CTRL1 0x20
52 #define _REG_CTRL1_A_ODR_SHIFT 4
53 #define _REG_CTRL1_A_ORD_MASK 0xF0
54 #define _REG_CTRL1_A_LP_EN 0x08
55 #define _REG_CTRL1_A_Z_EN 0x04
56 #define _REG_CTRL1_A_Y_EN 0x02
57 #define _REG_CTRL1_A_X_EN 0x01
58 #define _REG_CTRL1_A_XYZ_EN 0x07
59 
60 #define _REG_CTRL2 0x21
61 
62 #define _REG_CTRL2_A_HPM_SHIFT 6
63 #define _REG_CTRL2_A_HPM_MASK 0xC0
64 #define _REG_CTRL2_A_HPM_NORM_RST26 _MASK_VAL( _REG_CTRL2_A_HPM, 0x0 )
65 #define _REG_CTRL2_A_HPM_REFSIG _MASK_VAL( _REG_CTRL2_A_HPM, 0x1 )
66 #define _REG_CTRL2_A_HPM_NORM _MASK_VAL( _REG_CTRL2_A_HPM, 0x2 )
67 #define _REG_CTRL2_A_HPM_AUTORST _MASK_VAL( _REG_CTRL2_A_HPM, 0x3 )
68 
69 #define _REG_CTRL2_A_HPCF_SHIFT 4
70 #define _REG_CTRL2_A_HPCF_MASK 0x3
71 #define _REG_CTRL2_A_HPCF(V) _MASK_VAL(_REG_CTRL2_A_HPCF, V )
72 #define _REG_CTRL2_A_FDS 0x08
73 #define _REG_CTRL2_A_HPCLICK 0x04
74 #define _REG_CTRL2_A_HPIS2 0x02
75 #define _REG_CTRL2_A_HPIS1 0x01
76 
77 
78 #define _REG_CTRL4_A 0x23
79 #define _REG_CTRL4_A_BDU 0x80
80 #define _REG_CTRL4_A_BLE 0x40
81 #define _REG_CTRL4_A_FS_SHIFT 4
82 #define _REG_CTRL4_A_FS_MASK 0x30
83 #define _REG_CTRL4_A_FS(V) _MASK_VAL(_REG_CTRL4_A_FS, V)
84 #define _REG_CTRL4_A_HR 0x08
85 #define _REG_CTRL4_A_ST_SHIFT 1
86 #define _REG_CTRL4_A_ST_MASK 0x06
87 #define _REG_CTRL4_A_ST(V) _MASK_VAL(_REG_CTRL4_A_ST)
88 #define _REG_CTRL4_SPI_ENABLE 0x01
89 
90 #define _REG_OUT_X_L_A 0x28
91 #define _REG_OUT_X_H_A 0x29
92 #define _REG_OUT_Y_L_A 0x2A
93 #define _REG_OUT_Y_H_A 0x2B
94 #define _REG_OUT_Z_L_A 0x2C
95 #define _REG_OUT_Z_H_A 0x2D
96 
97 
98 // Magnetometer ID
99 #define _REG_WHO_AM_I_M 0x4F
100 #define _REG_WHO_AM_I_M_ID 0x40
101 
102 #define _REG_CFGA_M 0x60
103 #define _REG_CFGA_M_COMP_TEMP_EN 0x80
104 #define _REG_CFGA_M_REBOOT 0x40
105 #define _REG_CFGA_M_SOFT_RST 0x20
106 #define _REG_CFGA_M_LP 0x10
107 #define _REG_CFGA_M_ODR_SHIFT 2
108 #define _REG_CFGA_M_ODR_MASK 0x0C
109 #define _REG_CFGA_M_ODR(V) _MASK_VAL(_REG_CFGA_M_ODR, V)
110 #define _REG_CFGA_M_MD_SHIFT 0
111 #define _REG_CFGA_M_MD_MASK 0x03
112 #define _REG_CFGA_M_MD(V) _MASK_VAL(_REG_CFGA_M_MD, V)
113 
114 
115 #define _REG_CFGB_M 0x61
116 #define _REG_CFGB_M_OFF_CANC_OS 0x10
117 #define _REG_CFGB_M_INT_ON_DATA_OFF 0x08
118 #define _REG_CFGB_M_SET_FREQ 0x04
119 #define _REG_CFGB_M_OFF_CANC 0x02
120 #define _REG_CFGB_M_LPF 0x01
121 
122 
123 #define _REG_CFGC_M 0x62
124 #define _REG_CFGC_M_INT_MAG_PIN 0x40
125 #define _REG_CFGC_M_I2C_DIS 0x20
126 #define _REG_CFGC_M_BDU 0x10
127 #define _REG_CFGC_M_BLE 0x08
128 #define _REG_CFGC_M_SELF_TEST 0x02
129 #define _REG_CFGC_M_INT_MAG 0x01
130 
131 #define _REG_OUT_X_L_M 0x68
132 #define _REG_OUT_X_H_M 0x69
133 #define _REG_OUT_Y_L_M 0x6A
134 #define _REG_OUT_Y_H_M 0x6B
135 #define _REG_OUT_Z_L_M 0x6C
136 #define _REG_OUT_Z_H_M 0x6D
137 
138 bool lsm303AgrHasTemp(I2C_Device *dev, bool * hasData)
139 {
140  uint8_t t;
141  if (!i2cReadReg(dev, _ACC_ADDR, _REG_AUX_A, &t, 1)) return errRebase("LSM303AGR");
142  *hasData = t & _REG_AUX_A_TDA ? true : false;
143  return true;
144 }
145 
146 bool lsm303AgrTempRead(I2C_Device * dev, int16_t * temp)
147 {
148  uint8_t data[2];
149  uint8_t t;
150  if (!i2cReadReg(dev, _ACC_ADDR, _REG_AUX_A, &t, 1)) return errRebase("LSM303AGR");
151 
152  if (!(t & _REG_AUX_A_TDA)) return errSet(ERROR(E_INVSTATE));
153 
154  if (!i2cReadReg(dev, _ACC_ADDR, _REG_TEMP_OUT_L | _AUTO_INC_REG , data, sizeof(data)))
155  return errRebase("LSM303AGR");
156 
157  *temp = _lsm303RawDataToI16(data);
158 
159  return true;
160 }
161 
162 
163 bool lsm303AgrValid(I2C_Device * dev, bool * isLSM303Agr)
164 {
165  uint8_t reg_m,reg_a;
166  if (!i2cReadReg(dev, _MAG_ADDR, _REG_WHO_AM_I_M, &reg_m, 1)) return errRebase("LSM303AGR");
167  if (!i2cReadReg(dev, _ACC_ADDR, _REG_WHO_AM_I_A, &reg_a, 1)) return errRebase("LSM303AGR");
168  if (reg_m == _REG_WHO_AM_I_M_ID)
169  *isLSM303Agr = true;
170  else
171  *isLSM303Agr = false;
172 
173  return true;
174 }
175 
177 {
178  uint8_t data[6];
179  if (!i2cReadReg(dev, _MAG_ADDR, _REG_OUT_X_L_M | _AUTO_INC_REG, data, sizeof(data)))
180  return false;
181 
182  _lsm303RawDataToAxis(data, result);
183 
184  return true;
185 }
186 
187 
189 {
190  uint8_t data[6];
191  if (!i2cReadReg(dev, _ACC_ADDR, _REG_OUT_X_L_A | _AUTO_INC_REG, data, sizeof(data)))
192  return errRebase("LSM303");
193 
194  _lsm303RawDataToAxis(data, result);
195 
196  return true;
197 }
198 
199 
201 {
202  uint8_t t;
203 
204  t = config.lp ? _REG_CFGA_M_LP : 0;
205  t|= _REG_CFGA_M_ODR(config.rate);
206  t|= _REG_CFGA_M_MD(config.mode);
207  t|= config.tempCompEn ? _REG_CFGA_M_COMP_TEMP_EN : 0;
208  if (!i2cWriteReg(dev, _MAG_ADDR, _REG_CFGA_M, &t, sizeof(t))) goto err;
209 
210  t = config.lpf ? _REG_CFGB_M_LPF : 0;
211  t|= config.offCanc ? _REG_CFGB_M_OFF_CANC | _REG_CFGB_M_OFF_CANC_OS : 0;
212  if (!i2cWriteReg(dev, _MAG_ADDR, _REG_CFGB_M, &t, sizeof(t))) goto err;
213 
214  t = config.bdu ? _REG_CFGC_M_BDU : 0;
215  if (!i2cWriteReg(dev, _MAG_ADDR, _REG_CFGC_M, &t, sizeof(t))) goto err;
216 
217  return true;
218 err:
219  return errRebase("LSM303");
220 }
221 
222 
224 {
225  uint8_t t;
226 
227  // CTRL1_A
228  t = (config.rate << _REG_CTRL1_A_ODR_SHIFT) & _REG_CTRL1_A_ORD_MASK;
229  t|= config.pm == LSM303AGR_ACC_PM_LOW_8BIT ? _REG_CTRL1_A_LP_EN : 0;
230  t|= _REG_CTRL1_A_XYZ_EN;
231  if (!i2cWriteReg(dev, _ACC_ADDR, _REG_CTRL1, &t, 1)) goto err;
232 
233 
234  // CTRL2_A
235  // no IRQ support, so we'll skip all HPI* and HPCLICK functions
236  t = _REG_CTRL2_A_HPCF(config.hpcf);
237  t|= config.fds ? _REG_CTRL2_A_FDS : 0;
238  t|= _REG_CTRL2_A_HPM_NORM;
239  if (!i2cWriteReg(dev, _ACC_ADDR, _REG_CTRL2, &t, 1)) goto err;
240 
241  // CTRL3_A
242  // complete skip, we don't do IRQ
243 
244  // CTRL4_A
245  // skip self test, BLE, SPI
246  t = config.bdu ? _REG_CTRL4_A_BDU : 0;
247  t|= _REG_CTRL4_A_FS(config.fs);
248  t|= config.pm == LSM303AGR_ACC_PM_HIGH_12BIT ? _REG_CTRL4_A_HR : 0;
249  if (!i2cWriteReg(dev, _ACC_ADDR, _REG_CTRL4_A, &t, 1)) goto err;
250 
251  // CTRL5_A skipped
252  // CTRL6_A skipped
253 
254  // Temperature config reg, part of accelerometer
255  t = config.temp ? _REG_TEMP_CFG_ENABLE : _REG_TEMP_CFG_DISABLE;
256  if (!i2cWriteReg(dev, _ACC_ADDR, _REG_TEMP_CFG, &t, sizeof(t))) goto err;
257 
258  return true;
259 err:
260  return errRebase("LSM303");
261 }
262 
263 
Axis structure for 3D information.
Definition: lsm303.h:31
bool lp
Low power mode.
Definition: lsm303agr.h:94
bool tempCompEn
Temperature compensation enabled.
Definition: lsm303agr.h:93
Accelerator configuration structure.
Definition: lsm303agr.h:114
bool lsm303AgrAccCfg(I2C_Device *dev, Lsm303AgrAccCfg config)
Set the accelerometer configuration.
Definition: lsm303agr.c:223
Magnet configuration.
Definition: lsm303agr.h:90
uint16_t hpcf
High-pass filter, one of LSM303AG_ACC_HPCF_*.
Definition: lsm303agr.h:117
static uint16_t _lsm303RawDataToI16(uint8_t *data)
Function shared for both LSM303 drivers.
Definition: lsm303.h:41
void _lsm303RawDataToAxis(uint8_t *data, Lsm303Axis *axis)
Internal function shared for both LSM303 drivers.
Definition: lsm303.c:15
bool lsm303AgrAccRead(I2C_Device *dev, Lsm303Axis *result)
Read the accelerometer information.
Definition: lsm303agr.c:188
Structure defines OpenCores I2C Device.
Definition: dev_i2c.h:55
uint16_t mode
one of LSM303AGR_MAG_MODE_*
Definition: lsm303agr.h:91
bool lsm303AgrMagCfg(I2C_Device *dev, Lsm303AgrMagCfg config)
Set the Magnet configuration.
Definition: lsm303agr.c:200
uint16_t pm
Power mode.
Definition: lsm303agr.h:119
bool lsm303AgrValid(I2C_Device *dev, bool *isLSM303Agr)
Checks whether or not the lsm303Agr is valid.
Definition: lsm303agr.c:163
Driver for the ST lsm303Agr Compass sensor, which unlike the name suggests quite incompable to the LS...
#define E_INVSTATE
Generic error: Module is in a state in which.
Definition: errorcode.h:103
bool i2cReadReg(I2C_Device *dev, i2cAddr addr, uint8_t regNo, uint8_t *rd, int rdLen)
Reads from the I2C device register.
Definition: i2c.c:188
bool i2cWriteReg(I2C_Device *dev, i2cAddr addr, uint8_t regNo, uint8_t *wr, int wrLen)
Writes to the I2C device register.
Definition: i2c.c:247
bool lsm303AgrTempRead(I2C_Device *dev, int16_t *result)
Reads the temperature.
Definition: lsm303agr.c:146
bool offCanc
Offset cancellation.
Definition: lsm303agr.h:95
uint16_t rate
One of LSM303AGR_MAG_RATE_*.
Definition: lsm303agr.h:92
uint16_t rate
Accelerometer rate , one of LSM303AG_ACC_RATE_*.
Definition: lsm303agr.h:116
bool temp
Temperature sensor enable.
Definition: lsm303agr.h:121
bool bdu
Block data update.
Definition: lsm303agr.h:120
bool lpf
Enable low-pass filter.
Definition: lsm303agr.h:96
uint16_t fs
Full scale of accelerometer, one of LSM303AGR_ACC_FS_*.
Definition: lsm303agr.h:118
static bool errRebase(const char *name)
Rebases the cause of the error message.
Definition: err.h:104
bool fds
Filter data selection.
Definition: lsm303agr.h:122
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
bool bdu
Block date update enable.
Definition: lsm303agr.h:97
bool lsm303AgrMagRead(I2C_Device *dev, Lsm303Axis *result)
Read the magnet information.
Definition: lsm303agr.c:176