diff options
Diffstat (limited to 'lib/chibios/os/ex/devices/ST/l3gd20.c')
-rw-r--r-- | lib/chibios/os/ex/devices/ST/l3gd20.c | 642 |
1 files changed, 642 insertions, 0 deletions
diff --git a/lib/chibios/os/ex/devices/ST/l3gd20.c b/lib/chibios/os/ex/devices/ST/l3gd20.c new file mode 100644 index 000000000..82f5d544d --- /dev/null +++ b/lib/chibios/os/ex/devices/ST/l3gd20.c | |||
@@ -0,0 +1,642 @@ | |||
1 | /* | ||
2 | ChibiOS - Copyright (C) 2016..2019 Rocco Marco Guglielmi | ||
3 | |||
4 | This file is part of ChibiOS. | ||
5 | |||
6 | ChibiOS 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 3 of the License, or | ||
9 | (at your option) any later version. | ||
10 | |||
11 | ChibiOS 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 this program. If not, see <http://www.gnu.org/licenses/>. | ||
18 | |||
19 | */ | ||
20 | |||
21 | /** | ||
22 | * @file l3gd20.c | ||
23 | * @brief L3GD20 MEMS interface module code. | ||
24 | * | ||
25 | * @addtogroup L3GD20 | ||
26 | * @ingroup EX_ST | ||
27 | * @{ | ||
28 | */ | ||
29 | |||
30 | #include "hal.h" | ||
31 | #include "l3gd20.h" | ||
32 | |||
33 | /*===========================================================================*/ | ||
34 | /* Driver local definitions. */ | ||
35 | /*===========================================================================*/ | ||
36 | |||
37 | /*===========================================================================*/ | ||
38 | /* Driver exported variables. */ | ||
39 | /*===========================================================================*/ | ||
40 | |||
41 | /*===========================================================================*/ | ||
42 | /* Driver local variables and types. */ | ||
43 | /*===========================================================================*/ | ||
44 | |||
45 | /*===========================================================================*/ | ||
46 | /* Driver local functions. */ | ||
47 | /*===========================================================================*/ | ||
48 | |||
49 | #if (L3GD20_USE_SPI) || defined(__DOXYGEN__) | ||
50 | /** | ||
51 | * @brief Reads a generic register value using SPI. | ||
52 | * @pre The SPI interface must be initialized and the driver started. | ||
53 | * | ||
54 | * @param[in] spip pointer to the SPI interface | ||
55 | * @param[in] reg starting register address | ||
56 | * @param[in] n number of consecutive registers to read | ||
57 | * @param[in] b pointer to an output buffer. | ||
58 | */ | ||
59 | static void l3gd20SPIReadRegister(SPIDriver *spip, uint8_t reg, size_t n, | ||
60 | uint8_t* b) { | ||
61 | uint8_t cmd; | ||
62 | (n == 1) ? (cmd = reg | L3GD20_RW) : (cmd = reg | L3GD20_RW | L3GD20_MS); | ||
63 | spiSelect(spip); | ||
64 | spiSend(spip, 1, &cmd); | ||
65 | spiReceive(spip, n, b); | ||
66 | spiUnselect(spip); | ||
67 | } | ||
68 | |||
69 | /** | ||
70 | * @brief Writes a value into a generic register using SPI. | ||
71 | * @pre The SPI interface must be initialized and the driver started. | ||
72 | * | ||
73 | * @param[in] spip pointer to the SPI interface | ||
74 | * @param[in] reg starting register address | ||
75 | * @param[in] n number of adjacent registers to write | ||
76 | * @param[in] b pointer to a buffer of values. | ||
77 | */ | ||
78 | static void l3gd20SPIWriteRegister(SPIDriver *spip, uint8_t reg, size_t n, | ||
79 | uint8_t* b) { | ||
80 | uint8_t cmd; | ||
81 | (n == 1) ? (cmd = reg) : (cmd = reg | L3GD20_MS); | ||
82 | spiSelect(spip); | ||
83 | spiSend(spip, 1, &cmd); | ||
84 | spiSend(spip, n, b); | ||
85 | spiUnselect(spip); | ||
86 | } | ||
87 | #endif /* L3GD20_USE_SPI */ | ||
88 | |||
89 | /** | ||
90 | * @brief Return the number of axes of the BaseGyroscope. | ||
91 | * | ||
92 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
93 | * | ||
94 | * @return the number of axes. | ||
95 | */ | ||
96 | static size_t gyro_get_axes_number(void *ip) { | ||
97 | (void)ip; | ||
98 | |||
99 | return L3GD20_GYRO_NUMBER_OF_AXES; | ||
100 | } | ||
101 | |||
102 | /** | ||
103 | * @brief Retrieves raw data from the BaseGyroscope. | ||
104 | * @note This data is retrieved from MEMS register without any algebraical | ||
105 | * manipulation. | ||
106 | * @note The axes array must be at least the same size of the | ||
107 | * BaseGyroscope axes number. | ||
108 | * | ||
109 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
110 | * @param[out] axes a buffer which would be filled with raw data. | ||
111 | * | ||
112 | * @return The operation status. | ||
113 | * @retval MSG_OK if the function succeeded. | ||
114 | */ | ||
115 | static msg_t gyro_read_raw(void *ip, int32_t axes[L3GD20_GYRO_NUMBER_OF_AXES]) { | ||
116 | L3GD20Driver* devp; | ||
117 | int16_t tmp; | ||
118 | uint8_t i, buff [2 * L3GD20_GYRO_NUMBER_OF_AXES]; | ||
119 | msg_t msg = MSG_OK; | ||
120 | |||
121 | osalDbgCheck((ip != NULL) && (axes != NULL)); | ||
122 | |||
123 | /* Getting parent instance pointer.*/ | ||
124 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
125 | |||
126 | osalDbgAssert((devp->state == L3GD20_READY), | ||
127 | "gyro_read_raw(), invalid state"); | ||
128 | #if L3GD20_USE_SPI | ||
129 | osalDbgAssert((devp->config->spip->state == SPI_READY), | ||
130 | "gyro_read_raw(), channel not ready"); | ||
131 | |||
132 | #if L3GD20_SHARED_SPI | ||
133 | spiAcquireBus(devp->config->spip); | ||
134 | spiStart(devp->config->spip, | ||
135 | devp->config->spicfg); | ||
136 | #endif /* L3GD20_SHARED_SPI */ | ||
137 | |||
138 | l3gd20SPIReadRegister(devp->config->spip, L3GD20_AD_OUT_X_L, | ||
139 | L3GD20_GYRO_NUMBER_OF_AXES * 2, buff); | ||
140 | |||
141 | #if L3GD20_SHARED_SPI | ||
142 | spiReleaseBus(devp->config->spip); | ||
143 | #endif /* L3GD20_SHARED_SPI */ | ||
144 | #endif /* L3GD20_USE_SPI */ | ||
145 | |||
146 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
147 | tmp = buff[2 * i] + (buff[2 * i + 1] << 8); | ||
148 | axes[i] = (int32_t)tmp; | ||
149 | } | ||
150 | return msg; | ||
151 | } | ||
152 | |||
153 | /** | ||
154 | * @brief Retrieves cooked data from the BaseGyroscope. | ||
155 | * @note This data is manipulated according to the formula | ||
156 | * cooked = (raw * sensitivity) - bias. | ||
157 | * @note Final data is expressed as DPS. | ||
158 | * @note The axes array must be at least the same size of the | ||
159 | * BaseGyroscope axes number. | ||
160 | * | ||
161 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
162 | * @param[out] axes a buffer which would be filled with cooked data. | ||
163 | * | ||
164 | * @return The operation status. | ||
165 | * @retval MSG_OK if the function succeeded. | ||
166 | */ | ||
167 | static msg_t gyro_read_cooked(void *ip, float axes[]) { | ||
168 | L3GD20Driver* devp; | ||
169 | uint32_t i; | ||
170 | int32_t raw[L3GD20_GYRO_NUMBER_OF_AXES]; | ||
171 | msg_t msg; | ||
172 | |||
173 | osalDbgCheck((ip != NULL) && (axes != NULL)); | ||
174 | |||
175 | /* Getting parent instance pointer.*/ | ||
176 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
177 | |||
178 | osalDbgAssert((devp->state == L3GD20_READY), | ||
179 | "gyro_read_cooked(), invalid state"); | ||
180 | |||
181 | msg = gyro_read_raw(ip, raw); | ||
182 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++){ | ||
183 | axes[i] = (raw[i] * devp->gyrosensitivity[i]) - devp->gyrobias[i]; | ||
184 | } | ||
185 | return msg; | ||
186 | } | ||
187 | |||
188 | /** | ||
189 | * @brief Samples bias values for the BaseGyroscope. | ||
190 | * @note The L3GD20 shall not be moved during the whole procedure. | ||
191 | * @note After this function internal bias is automatically updated. | ||
192 | * @note The behavior of this function depends on @p L3GD20_BIAS_ACQ_TIMES | ||
193 | * and @p L3GD20_BIAS_SETTLING_US. | ||
194 | * | ||
195 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
196 | * | ||
197 | * @return The operation status. | ||
198 | * @retval MSG_OK if the function succeeded. | ||
199 | */ | ||
200 | static msg_t gyro_sample_bias(void *ip) { | ||
201 | L3GD20Driver* devp; | ||
202 | uint32_t i, j; | ||
203 | int32_t raw[L3GD20_GYRO_NUMBER_OF_AXES]; | ||
204 | int32_t buff[L3GD20_GYRO_NUMBER_OF_AXES] = {0, 0, 0}; | ||
205 | msg_t msg; | ||
206 | |||
207 | osalDbgCheck(ip != NULL); | ||
208 | |||
209 | /* Getting parent instance pointer.*/ | ||
210 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
211 | |||
212 | osalDbgAssert((devp->state == L3GD20_READY), | ||
213 | "gyro_sample_bias(), invalid state"); | ||
214 | #if L3GD20_USE_SPI | ||
215 | osalDbgAssert((devp->config->spip->state == SPI_READY), | ||
216 | "gyro_sample_bias(), channel not ready"); | ||
217 | #endif | ||
218 | |||
219 | for(i = 0; i < L3GD20_BIAS_ACQ_TIMES; i++){ | ||
220 | msg = gyro_read_raw(ip, raw); | ||
221 | if(msg != MSG_OK) | ||
222 | return msg; | ||
223 | for(j = 0; j < L3GD20_GYRO_NUMBER_OF_AXES; j++){ | ||
224 | buff[j] += raw[j]; | ||
225 | } | ||
226 | osalThreadSleepMicroseconds(L3GD20_BIAS_SETTLING_US); | ||
227 | } | ||
228 | |||
229 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++){ | ||
230 | devp->gyrobias[i] = (buff[i] / L3GD20_BIAS_ACQ_TIMES); | ||
231 | devp->gyrobias[i] *= devp->gyrosensitivity[i]; | ||
232 | } | ||
233 | return msg; | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * @brief Set bias values for the BaseGyroscope. | ||
238 | * @note Bias must be expressed as DPS. | ||
239 | * @note The bias buffer must be at least the same size of the BaseGyroscope | ||
240 | * axes number. | ||
241 | * | ||
242 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
243 | * @param[in] bp a buffer which contains biases. | ||
244 | * | ||
245 | * @return The operation status. | ||
246 | * @retval MSG_OK if the function succeeded. | ||
247 | */ | ||
248 | static msg_t gyro_set_bias(void *ip, float *bp) { | ||
249 | L3GD20Driver* devp; | ||
250 | uint32_t i; | ||
251 | msg_t msg = MSG_OK; | ||
252 | |||
253 | osalDbgCheck((ip != NULL) && (bp != NULL)); | ||
254 | |||
255 | /* Getting parent instance pointer.*/ | ||
256 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
257 | |||
258 | osalDbgAssert((devp->state == L3GD20_READY), | ||
259 | "gyro_set_bias(), invalid state"); | ||
260 | |||
261 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
262 | devp->gyrobias[i] = bp[i]; | ||
263 | } | ||
264 | return msg; | ||
265 | } | ||
266 | |||
267 | /** | ||
268 | * @brief Reset bias values for the BaseGyroscope. | ||
269 | * @note Default biases value are obtained from device datasheet when | ||
270 | * available otherwise they are considered zero. | ||
271 | * | ||
272 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
273 | * | ||
274 | * @return The operation status. | ||
275 | * @retval MSG_OK if the function succeeded. | ||
276 | */ | ||
277 | static msg_t gyro_reset_bias(void *ip) { | ||
278 | L3GD20Driver* devp; | ||
279 | uint32_t i; | ||
280 | msg_t msg = MSG_OK; | ||
281 | |||
282 | osalDbgCheck(ip != NULL); | ||
283 | |||
284 | /* Getting parent instance pointer.*/ | ||
285 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
286 | |||
287 | osalDbgAssert((devp->state == L3GD20_READY), | ||
288 | "gyro_reset_bias(), invalid state"); | ||
289 | |||
290 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) | ||
291 | devp->gyrobias[i] = L3GD20_GYRO_BIAS; | ||
292 | return msg; | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * @brief Set sensitivity values for the BaseGyroscope. | ||
297 | * @note Sensitivity must be expressed as DPS/LSB. | ||
298 | * @note The sensitivity buffer must be at least the same size of the | ||
299 | * BaseGyroscope axes number. | ||
300 | * | ||
301 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
302 | * @param[in] sp a buffer which contains sensitivities. | ||
303 | * | ||
304 | * @return The operation status. | ||
305 | * @retval MSG_OK if the function succeeded. | ||
306 | */ | ||
307 | static msg_t gyro_set_sensivity(void *ip, float *sp) { | ||
308 | L3GD20Driver* devp; | ||
309 | uint32_t i; | ||
310 | msg_t msg = MSG_OK; | ||
311 | |||
312 | osalDbgCheck((ip != NULL) && (sp !=NULL)); | ||
313 | |||
314 | /* Getting parent instance pointer.*/ | ||
315 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
316 | |||
317 | osalDbgAssert((devp->state == L3GD20_READY), | ||
318 | "gyro_set_sensivity(), invalid state"); | ||
319 | |||
320 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
321 | devp->gyrosensitivity[i] = sp[i]; | ||
322 | } | ||
323 | return msg; | ||
324 | } | ||
325 | |||
326 | /** | ||
327 | * @brief Reset sensitivity values for the BaseGyroscope. | ||
328 | * @note Default sensitivities value are obtained from device datasheet. | ||
329 | * | ||
330 | * @param[in] ip pointer to @p BaseGyroscope interface. | ||
331 | * | ||
332 | * @return The operation status. | ||
333 | * @retval MSG_OK if the function succeeded. | ||
334 | * @retval MSG_RESET otherwise. | ||
335 | */ | ||
336 | static msg_t gyro_reset_sensivity(void *ip) { | ||
337 | L3GD20Driver* devp; | ||
338 | uint32_t i; | ||
339 | msg_t msg = MSG_OK; | ||
340 | |||
341 | osalDbgCheck(ip != NULL); | ||
342 | |||
343 | /* Getting parent instance pointer.*/ | ||
344 | devp = objGetInstance(L3GD20Driver*, (BaseGyroscope*)ip); | ||
345 | |||
346 | osalDbgAssert((devp->state == L3GD20_READY), | ||
347 | "gyro_reset_sensivity(), invalid state"); | ||
348 | |||
349 | if(devp->config->gyrofullscale == L3GD20_FS_250DPS) | ||
350 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) | ||
351 | devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_250DPS; | ||
352 | else if(devp->config->gyrofullscale == L3GD20_FS_500DPS) | ||
353 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) | ||
354 | devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_500DPS; | ||
355 | else if(devp->config->gyrofullscale == L3GD20_FS_2000DPS) | ||
356 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) | ||
357 | devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_2000DPS; | ||
358 | else { | ||
359 | osalDbgAssert(FALSE, "gyro_reset_sensivity(), full scale issue"); | ||
360 | return MSG_RESET; | ||
361 | } | ||
362 | return msg; | ||
363 | } | ||
364 | |||
365 | /** | ||
366 | * @brief Changes the L3GD20Driver gyroscope fullscale value. | ||
367 | * @note This function also rescale sensitivities and biases based on | ||
368 | * previous and next fullscale value. | ||
369 | * @note A recalibration is highly suggested after calling this function. | ||
370 | * | ||
371 | * @param[in] devp pointer to @p BaseGyroscope interface. | ||
372 | * @param[in] fs new fullscale value. | ||
373 | * | ||
374 | * @return The operation status. | ||
375 | * @retval MSG_OK if the function succeeded. | ||
376 | * @retval MSG_RESET otherwise. | ||
377 | */ | ||
378 | static msg_t gyro_set_full_scale(L3GD20Driver *devp, l3gd20_fs_t fs) { | ||
379 | float newfs, scale; | ||
380 | uint8_t i, cr; | ||
381 | msg_t msg = MSG_OK; | ||
382 | |||
383 | osalDbgCheck(devp != NULL); | ||
384 | |||
385 | osalDbgAssert((devp->state == L3GD20_READY), | ||
386 | "gyro_set_full_scale(), invalid state"); | ||
387 | #if L3GD20_USE_SPI | ||
388 | osalDbgAssert((devp->config->spip->state == SPI_READY), | ||
389 | "gyro_set_full_scale(), channel not ready"); | ||
390 | #endif | ||
391 | |||
392 | if(fs == L3GD20_FS_250DPS) { | ||
393 | newfs = L3GD20_250DPS; | ||
394 | } | ||
395 | else if(fs == L3GD20_FS_500DPS) { | ||
396 | newfs = L3GD20_500DPS; | ||
397 | } | ||
398 | else if(fs == L3GD20_FS_2000DPS) { | ||
399 | newfs = L3GD20_2000DPS; | ||
400 | } | ||
401 | else { | ||
402 | return MSG_RESET; | ||
403 | } | ||
404 | |||
405 | if(newfs != devp->gyrofullscale) { | ||
406 | scale = newfs / devp->gyrofullscale; | ||
407 | devp->gyrofullscale = newfs; | ||
408 | |||
409 | #if L3GD20_USE_SPI | ||
410 | #if L3GD20_SHARED_SPI | ||
411 | spiAcquireBus(devp->config->spip); | ||
412 | spiStart(devp->config->spip, | ||
413 | devp->config->spicfg); | ||
414 | #endif /* L3GD20_SHARED_SPI */ | ||
415 | |||
416 | /* Updating register.*/ | ||
417 | l3gd20SPIReadRegister(devp->config->spip, | ||
418 | L3GD20_AD_CTRL_REG4, 1, &cr); | ||
419 | |||
420 | #if L3GD20_SHARED_SPI | ||
421 | spiReleaseBus(devp->config->spip); | ||
422 | #endif /* L3GD20_SHARED_SPI */ | ||
423 | #endif /* L3GD20_USE_SPI */ | ||
424 | cr &= ~(L3GD20_CTRL_REG4_FS_MASK); | ||
425 | cr |= fs; | ||
426 | |||
427 | #if L3GD20_USE_SPI | ||
428 | #if L3GD20_SHARED_SPI | ||
429 | spiAcquireBus(devp->config->spip); | ||
430 | spiStart(devp->config->spip, | ||
431 | devp->config->spicfg); | ||
432 | #endif /* L3GD20_SHARED_SPI */ | ||
433 | |||
434 | l3gd20SPIWriteRegister(devp->config->spip, | ||
435 | L3GD20_AD_CTRL_REG4, 1, &cr); | ||
436 | #if L3GD20_SHARED_SPI | ||
437 | spiReleaseBus(devp->config->spip); | ||
438 | #endif /* L3GD20_SHARED_SPI */ | ||
439 | #endif /* L3GD20_USE_SPI */ | ||
440 | |||
441 | /* Scaling sensitivity and bias. Re-calibration is suggested anyway. */ | ||
442 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
443 | devp->gyrosensitivity[i] *= scale; | ||
444 | devp->gyrobias[i] *= scale; | ||
445 | } | ||
446 | } | ||
447 | return msg; | ||
448 | } | ||
449 | |||
450 | static const struct L3GD20VMT vmt_device = { | ||
451 | (size_t)0, | ||
452 | gyro_set_full_scale | ||
453 | }; | ||
454 | |||
455 | static const struct BaseGyroscopeVMT vmt_gyroscope = { | ||
456 | sizeof(struct L3GD20VMT*), | ||
457 | gyro_get_axes_number, gyro_read_raw, gyro_read_cooked, | ||
458 | gyro_sample_bias, gyro_set_bias, gyro_reset_bias, | ||
459 | gyro_set_sensivity, gyro_reset_sensivity | ||
460 | }; | ||
461 | |||
462 | /*===========================================================================*/ | ||
463 | /* Driver exported functions. */ | ||
464 | /*===========================================================================*/ | ||
465 | |||
466 | /** | ||
467 | * @brief Initializes an instance. | ||
468 | * | ||
469 | * @param[out] devp pointer to the @p L3GD20Driver object | ||
470 | * | ||
471 | * @init | ||
472 | */ | ||
473 | void l3gd20ObjectInit(L3GD20Driver *devp) { | ||
474 | devp->vmt = &vmt_device; | ||
475 | devp->gyro_if.vmt = &vmt_gyroscope; | ||
476 | |||
477 | devp->config = NULL; | ||
478 | |||
479 | devp->state = L3GD20_STOP; | ||
480 | } | ||
481 | |||
482 | /** | ||
483 | * @brief Configures and activates L3GD20 Complex Driver peripheral. | ||
484 | * | ||
485 | * @param[in] devp pointer to the @p L3GD20Driver object | ||
486 | * @param[in] config pointer to the @p L3GD20Config object | ||
487 | * | ||
488 | * @api | ||
489 | */ | ||
490 | void l3gd20Start(L3GD20Driver *devp, const L3GD20Config *config) { | ||
491 | uint32_t i; | ||
492 | uint8_t cr[5] = {0, 0, 0, 0, 0}; | ||
493 | osalDbgCheck((devp != NULL) && (config != NULL)); | ||
494 | |||
495 | osalDbgAssert((devp->state == L3GD20_STOP) || (devp->state == L3GD20_READY), | ||
496 | "l3gd20Start(), invalid state"); | ||
497 | |||
498 | devp->config = config; | ||
499 | |||
500 | /* Control register 1 configuration block.*/ | ||
501 | { | ||
502 | cr[0] = L3GD20_CTRL_REG1_XEN | L3GD20_CTRL_REG1_YEN | | ||
503 | L3GD20_CTRL_REG1_ZEN | L3GD20_CTRL_REG1_PD | | ||
504 | devp->config->gyrooutputdatarate; | ||
505 | #if L3GD20_USE_ADVANCED || defined(__DOXYGEN__) | ||
506 | cr[0] |= devp->config->gyrobandwidth; | ||
507 | #endif | ||
508 | } | ||
509 | |||
510 | /* Control register 2 configuration block.*/ | ||
511 | { | ||
512 | #if L3GD20_USE_ADVANCED || defined(__DOXYGEN__) | ||
513 | if(devp->config->gyrohpmode != L3GD20_HPM_BYPASSED) | ||
514 | cr[1] = devp->config->gyrohpmode | devp->config->gyrohpconfiguration; | ||
515 | #endif | ||
516 | } | ||
517 | |||
518 | /* Control register 4 configuration block.*/ | ||
519 | { | ||
520 | cr[3] = devp->config->gyrofullscale; | ||
521 | #if L3GD20_USE_ADVANCED || defined(__DOXYGEN__) | ||
522 | cr[3] |= devp->config->gyroblockdataupdate | | ||
523 | devp->config->gyroendianness; | ||
524 | #endif | ||
525 | } | ||
526 | |||
527 | /* Control register 5 configuration block.*/ | ||
528 | { | ||
529 | #if L3GD20_USE_ADVANCED || defined(__DOXYGEN__) | ||
530 | if((devp->config->gyrohpmode != L3GD20_HPM_BYPASSED)) { | ||
531 | cr[4] = L3GD20_CTRL_REG5_HPEN; | ||
532 | if(devp->config->gyrolp2mode != L3GD20_LP2M_BYPASSED) { | ||
533 | cr[4] |= L3GD20_CTRL_REG5_INT1_SEL1 | | ||
534 | L3GD20_CTRL_REG5_OUT_SEL1; | ||
535 | } | ||
536 | else { | ||
537 | cr[4] |= L3GD20_CTRL_REG5_INT1_SEL0 | | ||
538 | L3GD20_CTRL_REG5_OUT_SEL0; | ||
539 | } | ||
540 | } | ||
541 | #endif | ||
542 | } | ||
543 | |||
544 | #if L3GD20_USE_SPI | ||
545 | #if L3GD20_SHARED_SPI | ||
546 | spiAcquireBus(devp->config->spip); | ||
547 | #endif /* L3GD20_SHARED_SPI */ | ||
548 | spiStart(devp->config->spip, | ||
549 | devp->config->spicfg); | ||
550 | |||
551 | l3gd20SPIWriteRegister(devp->config->spip, L3GD20_AD_CTRL_REG1, | ||
552 | 5, cr); | ||
553 | #if L3GD20_SHARED_SPI | ||
554 | spiReleaseBus(devp->config->spip); | ||
555 | #endif /* L3GD20_SHARED_SPI */ | ||
556 | #endif /* L3GD20_USE_SPI */ | ||
557 | |||
558 | /* Storing sensitivity information according to full scale.*/ | ||
559 | if(devp->config->gyrofullscale == L3GD20_FS_250DPS) { | ||
560 | devp->gyrofullscale = L3GD20_250DPS; | ||
561 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
562 | if (devp->config->gyrosensitivity == NULL) | ||
563 | devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_250DPS; | ||
564 | else | ||
565 | devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i]; | ||
566 | } | ||
567 | } | ||
568 | else if(devp->config->gyrofullscale == L3GD20_FS_500DPS) { | ||
569 | devp->gyrofullscale = L3GD20_500DPS; | ||
570 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
571 | if (devp->config->gyrosensitivity == NULL) | ||
572 | devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_500DPS; | ||
573 | else | ||
574 | devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i]; | ||
575 | } | ||
576 | } | ||
577 | else if(devp->config->gyrofullscale == L3GD20_FS_2000DPS) { | ||
578 | devp->gyrofullscale = L3GD20_2000DPS; | ||
579 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
580 | if (devp->config->gyrosensitivity == NULL) | ||
581 | devp->gyrosensitivity[i] = L3GD20_GYRO_SENS_2000DPS; | ||
582 | else | ||
583 | devp->gyrosensitivity[i] = devp->config->gyrosensitivity[i]; | ||
584 | } | ||
585 | } | ||
586 | else | ||
587 | osalDbgAssert(FALSE, "l3gd20Start(), full scale issue"); | ||
588 | |||
589 | /* Storing bias information.*/ | ||
590 | if(devp->config->gyrobias != NULL) { | ||
591 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) { | ||
592 | devp->gyrobias[i] = devp->config->gyrobias[i]; | ||
593 | } | ||
594 | } | ||
595 | else { | ||
596 | for(i = 0; i < L3GD20_GYRO_NUMBER_OF_AXES; i++) | ||
597 | devp->gyrobias[i] = L3GD20_GYRO_BIAS; | ||
598 | } | ||
599 | |||
600 | /* This is the Gyroscope transient recovery time.*/ | ||
601 | osalThreadSleepMilliseconds(10); | ||
602 | |||
603 | devp->state = L3GD20_READY; | ||
604 | } | ||
605 | |||
606 | /** | ||
607 | * @brief Deactivates the L3GD20 Complex Driver peripheral. | ||
608 | * | ||
609 | * @param[in] devp pointer to the @p L3GD20Driver object | ||
610 | * | ||
611 | * @api | ||
612 | */ | ||
613 | void l3gd20Stop(L3GD20Driver *devp) { | ||
614 | uint8_t cr1; | ||
615 | osalDbgCheck(devp != NULL); | ||
616 | |||
617 | osalDbgAssert((devp->state == L3GD20_STOP) || (devp->state == L3GD20_READY), | ||
618 | "l3gd20Stop(), invalid state"); | ||
619 | |||
620 | if (devp->state == L3GD20_READY) { | ||
621 | /* Disabling all axes and enabling power down mode.*/ | ||
622 | cr1 = 0; | ||
623 | |||
624 | #if L3GD20_USE_SPI | ||
625 | #if L3GD20_SHARED_SPI | ||
626 | spiAcquireBus(devp->config->spip); | ||
627 | spiStart(devp->config->spip, | ||
628 | devp->config->spicfg); | ||
629 | #endif /* L3GD20_SHARED_SPI */ | ||
630 | |||
631 | l3gd20SPIWriteRegister(devp->config->spip, L3GD20_AD_CTRL_REG1, | ||
632 | 1, &cr1); | ||
633 | spiStop(devp->config->spip); | ||
634 | |||
635 | #if L3GD20_SHARED_SPI | ||
636 | spiReleaseBus(devp->config->spip); | ||
637 | #endif /* L3GD20_SHARED_SPI */ | ||
638 | #endif /* L3GD20_USE_SPI */ | ||
639 | } | ||
640 | devp->state = L3GD20_STOP; | ||
641 | } | ||
642 | /** @} */ | ||