aboutsummaryrefslogtreecommitdiff
path: root/lib/chibios/os/ex/devices/ST/l3gd20.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/chibios/os/ex/devices/ST/l3gd20.c')
-rw-r--r--lib/chibios/os/ex/devices/ST/l3gd20.c642
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 */
59static 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 */
78static 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 */
96static 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 */
115static 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 */
167static 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 */
200static 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 */
248static 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 */
277static 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 */
307static 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 */
336static 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 */
378static 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
450static const struct L3GD20VMT vmt_device = {
451 (size_t)0,
452 gyro_set_full_scale
453};
454
455static 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 */
473void 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 */
490void 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 */
613void 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/** @} */