Contiki 3.x
lis3dh.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Eistec AB.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  * notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  * notice, this list of conditions and the following disclaimer in the
12  * documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the copyright holder nor the names of its contributors
14  * may be used to endorse or promote products derived from this software
15  * without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * This file is part of the Mulle platform port of the Contiki operating system.
30  *
31  */
32 
33 /**
34  * \file
35  * Implementation of LIS3DH SPI driver used in the Mulle platform.
36  *
37  * \author
38  * Joakim Gebart <joakim.gebart@eistec.se>
39  */
40 
41 #include "lis3dh.h"
42 #include <stdint.h>
43 #include <stdio.h>
44 
45 /**
46  * Set bits of an 8-bit register on the LIS3DH.
47  */
48 void
49 lis3dh_set_bits(const lis3dh_reg_addr_t addr, const uint8_t mask)
50 {
51  uint8_t reg;
52 
53  reg = lis3dh_read_byte(addr);
54  reg |= mask;
55  lis3dh_write_byte(addr, reg);
56 }
57 /**
58  * Clear bits of an 8-bit register on the LIS3DH.
59  */
60 void
61 lis3dh_clear_bits(const lis3dh_reg_addr_t addr, const uint8_t mask)
62 {
63  uint8_t reg;
64 
65  reg = lis3dh_read_byte(addr);
66  reg &= ~mask;
67  lis3dh_write_byte(addr, reg);
68 }
69 /**
70  * Write (both set and clear) bits of an 8-bit register on the LIS3DH.
71  *
72  * \param addr Register address on the LIS3DH.
73  * \param mask Bitmask for the bits to modify.
74  * \param values The values to write to the masked bits.
75  */
76 void
77 lis3dh_write_bits(const lis3dh_reg_addr_t addr, const uint8_t mask,
78  const uint8_t values)
79 {
80  uint8_t reg;
81 
82  reg = lis3dh_read_byte(addr);
83  reg &= ~mask;
84  reg |= (values & mask);
85  lis3dh_write_byte(addr, reg);
86 }
87 /**
88  * Get one X-axis reading from the accelerometer.
89  *
90  * \return The oldest X axis acceleration measurement available.
91  */
92 int16_t
94 {
95  return lis3dh_read_int16(OUT_X_L);
96 }
97 /**
98  * Get one Y-axis reading from the accelerometer.
99  *
100  * \return The oldest Y axis acceleration measurement available.
101  */
102 int16_t
104 {
105  return lis3dh_read_int16(OUT_Y_L);
106 }
107 /**
108  * Get one Z-axis reading from the accelerometer.
109  *
110  * \return The oldest Z axis acceleration measurement available.
111  */
112 int16_t
114 {
115  return lis3dh_read_int16(OUT_Z_L);
116 }
117 /**
118  * Read all three axes in a single transaction.
119  *
120  * \param buffer Pointer to an int16_t[3] buffer.
121  */
122 void
123 lis3dh_read_xyz(int16_t *buffer)
124 {
125  lis3dh_memcpy_from_device(OUT_X_L, (uint8_t *)buffer,
127 }
128 /**
129  * Get one reading from the first channel of the auxiliary ADC.
130  *
131  * \return The current ADC reading.
132  */
133 int16_t
135 {
136  return lis3dh_read_int16(OUT_AUX_ADC1_L);
137 }
138 /**
139  * Get one reading from the second channel of the auxiliary ADC.
140  *
141  * \return The current ADC reading.
142  */
143 int16_t
145 {
146  return lis3dh_read_int16(OUT_AUX_ADC2_L);
147 }
148 /**
149  * Get one reading from the third channel of the auxiliary ADC.
150  *
151  * \note The internal temperature sensor is connected to the third channel on
152  * the auxiliary ADC when the TEMP_EN bit of TEMP_CFG_REG is set.
153  *
154  * \return The current ADC reading.
155  */
156 int16_t
158 {
159  return lis3dh_read_int16(OUT_AUX_ADC3_L);
160 }
161 /**
162  * Turn on/off power to the auxiliary ADC in LIS3DH.
163  *
164  * \param enable Power state of the auxiliary ADC
165  * \param temperature If not zero, switch the ADC mux so that a temperature
166  * reading is available on OUT_3_L, OUT_3_H.
167  *
168  * \note This ADC is only used for the temperature reading and the external ADC
169  * pins. The accelerometer ADC is turned on by lis3dh_set_odr().
170  */
171 void
172 lis3dh_set_aux_adc(const uint8_t enable, const uint8_t temperature)
173 {
175  (enable ? LIS3DH_TEMP_CFG_REG_ADC_PD_MASK : 0) |
176  (temperature ? LIS3DH_TEMP_CFG_REG_TEMP_EN_MASK : 0));
177 }
178 /**
179  * Enable/disable accelerometer axes.
180  *
181  * \param axes An OR-ed combination of LIS3DH_AXES_X, LIS3DH_AXES_Y, LIS3DH_AXES_Z.
182  *
183  * \note The macro LIS3DH_AXES_XYZ is a convenience shortcut to enable all axes.
184  */
185 void
186 lis3dh_set_axes(const uint8_t axes)
187 {
188  lis3dh_write_bits(CTRL_REG1, LIS3DH_CTRL_REG1_XYZEN_MASK, axes);
189 }
190 /**
191  * Set the FIFO mode.
192  *
193  * \param mode The chosen FIFO mode.
194  */
195 void
197 {
198  lis3dh_write_bits(FIFO_CTRL_REG, LIS3DH_FIFO_CTRL_REG_FM_MASK,
199  (mode << LIS3DH_FIFO_CTRL_REG_FM_SHIFT));
200 }
201 /**
202  * Enable/disable the FIFO.
203  *
204  * \param enable If zero, disable the FIFO, otherwise enables the FIFO.
205  */
206 void
207 lis3dh_set_fifo(const uint8_t enable)
208 {
210  (enable ? LIS3DH_CTRL_REG5_FIFO_EN_MASK : 0));
211 }
212 /**
213  * Set the output data rate of the sensor.
214  *
215  * \param odr Chosen output data rate.
216  */
217 void
219 {
220  lis3dh_write_bits(CTRL_REG1, LIS3DH_CTRL_REG1_ODR_MASK,
221  (odr << LIS3DH_CTRL_REG1_ODR_SHIFT));
222 }
223 /**
224  * Set the full scale range of the sensor.
225  *
226  * Valid values for scale is 2, 4, 8, 16 and represents the full range of the sensor.
227  *
228  * \param scale The chosen sensitivity scale.
229  */
230 void
232 {
233  switch(scale) {
234  case SCALE_2G:
235  lis3dh_write_bits(CTRL_REG4, LIS3DH_CTRL_REG4_FS_MASK,
236  LIS3DH_CTRL_REG4_FS_2G);
237  break;
238  case SCALE_4G:
239  lis3dh_write_bits(CTRL_REG4, LIS3DH_CTRL_REG4_FS_MASK,
240  LIS3DH_CTRL_REG4_FS_4G);
241  break;
242  case SCALE_8G:
243  lis3dh_write_bits(CTRL_REG4, LIS3DH_CTRL_REG4_FS_MASK,
244  LIS3DH_CTRL_REG4_FS_8G);
245  break;
246  case SCALE_16G:
247  lis3dh_write_bits(CTRL_REG4, LIS3DH_CTRL_REG4_FS_MASK,
248  LIS3DH_CTRL_REG4_FS_16G);
249  break;
250  default:
251  /* Invalid scale value */
252  return;
253  }
254 }
255 /**
256  * Initialize a LIS3DH accelerometer.
257  *
258  * \todo Signal errors when initializing the LIS3DH hardware.
259  */
260 void
262 {
263  uint8_t databyte;
264 
266 
267  databyte = lis3dh_read_byte(WHO_AM_I);
268  if(databyte != LIS3DH_WHO_AM_I_RESPONSE) {
269  /* Chip is not responding correctly */
270  return;
271  }
272 
273  /* Set block data update and little endian mode. */
274  lis3dh_write_byte(CTRL_REG4,
275  (LIS3DH_CTRL_REG4_BDU_ENABLE |
276  LIS3DH_CTRL_REG4_BLE_LITTLE_ENDIAN));
277 }
#define LIS3DH_WHO_AM_I_RESPONSE
The WHO_AM_I register should contain this value in order to correctly identify the chip...
Definition: lis3dh.h:54
#define LIS3DH_CTRL_REG1_ODR_SHIFT
Data rate selection.
Definition: lis3dh.h:118
int16_t lis3dh_read_aux_adc3()
Get one reading from the third channel of the auxiliary ADC.
Definition: lis3dh.c:157
void lis3dh_set_fifo(const uint8_t enable)
Enable/disable the FIFO.
Definition: lis3dh.c:207
#define LIS3DH_CTRL_REG5_FIFO_EN_MASK
FIFO enable.
Definition: lis3dh.h:340
lis3dh_reg_addr_t
All LIS3DH hardware registers are enumerated here.
Definition: lis3dh.h:59
int16_t lis3dh_read_int16(const lis3dh_reg_addr_t lsb_addr)
Read a 16-bit integer from the LIS3DH.
Definition: lis3dh-arch.c:127
lis3dh_fifo_mode_t
Allowed FIFO modes.
Definition: lis3dh.h:432
void lis3dh_set_fifo_mode(const lis3dh_fifo_mode_t mode)
Set the FIFO mode.
Definition: lis3dh.c:196
void lis3dh_memcpy_from_device(const lis3dh_reg_addr_t start_address, uint8_t *buffer, uint8_t count)
Read multiple bytes from the LIS3DH.
Definition: lis3dh-arch.c:160
lis3dh_scale_t
Scale parameters, use these names when calling lis3dh_set_scale(scale).
Definition: lis3dh.h:304
int16_t lis3dh_read_yaxis()
Get one Y-axis reading from the accelerometer.
Definition: lis3dh.c:103
#define LIS3DH_ACC_DATA_SIZE
Length of X, Y, Z data in bytes.
Definition: lis3dh.h:476
void lis3dh_arch_init()
Perform the platform specific part of the initialization process of the LIS3DH.
Definition: lis3dh-arch.c:231
void lis3dh_set_scale(const lis3dh_scale_t scale)
Set the full scale range of the sensor.
Definition: lis3dh.c:231
int16_t lis3dh_read_aux_adc2()
Get one reading from the second channel of the auxiliary ADC.
Definition: lis3dh.c:144
void lis3dh_read_xyz(int16_t *buffer)
Read all three axes in a single transaction.
Definition: lis3dh.c:123
int16_t lis3dh_read_zaxis()
Get one Z-axis reading from the accelerometer.
Definition: lis3dh.c:113
#define LIS3DH_TEMP_CFG_REG_ADC_PD_MASK
ADC enable.
Definition: lis3dh.h:107
lis3dh_odr_t
Allowed values for the Output Data Rate of the sensor.
Definition: lis3dh.h:149
void lis3dh_write_bits(const lis3dh_reg_addr_t addr, const uint8_t mask, const uint8_t values)
Write (both set and clear) bits of an 8-bit register on the LIS3DH.
Definition: lis3dh.c:77
void lis3dh_set_axes(const uint8_t axes)
Enable/disable accelerometer axes.
Definition: lis3dh.c:186
Interface of LIS3DH SPI driver used in the Mulle platform.
void lis3dh_init()
Initialize a LIS3DH accelerometer.
Definition: lis3dh.c:261
void lis3dh_set_odr(const lis3dh_odr_t odr)
Set the output data rate of the sensor.
Definition: lis3dh.c:218
#define LIS3DH_TEMP_CFG_REG_TEMP_EN_MASK
Temperature sensor (T) enable.
Definition: lis3dh.h:112
void lis3dh_set_bits(const lis3dh_reg_addr_t addr, const uint8_t mask)
Set bits of an 8-bit register on the LIS3DH.
Definition: lis3dh.c:49
void lis3dh_write_byte(const lis3dh_reg_addr_t addr, const uint8_t value)
Write a single byte to the LIS3DH.
Definition: lis3dh-arch.c:95
void lis3dh_clear_bits(const lis3dh_reg_addr_t addr, const uint8_t mask)
Clear bits of an 8-bit register on the LIS3DH.
Definition: lis3dh.c:61
void lis3dh_set_aux_adc(const uint8_t enable, const uint8_t temperature)
Turn on/off power to the auxiliary ADC in LIS3DH.
Definition: lis3dh.c:172
int16_t lis3dh_read_xaxis()
Get one X-axis reading from the accelerometer.
Definition: lis3dh.c:93
uint8_t lis3dh_read_byte(const lis3dh_reg_addr_t addr)
Read a single byte from the LIS3DH.
Definition: lis3dh-arch.c:109
int16_t lis3dh_read_aux_adc1()
Get one reading from the first channel of the auxiliary ADC.
Definition: lis3dh.c:134