Contiki 3.x
grove-gyro.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2016, Zolertia <http://www.zolertia.com>
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 Institute 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 INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18  * 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 INSTITUTE OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * This file is part of the Contiki operating system.
30  *
31  */
32 /*---------------------------------------------------------------------------*/
33 /**
34  * \addtogroup zoul-grove-gyro-sensor
35  * @{
36  *
37  * \file
38  * Grove's 3-axis gyroscope driver
39  * \author
40  * Antonio Lignan <alinan@zolertia.com>
41  */
42 /*---------------------------------------------------------------------------*/
43 #include <stdio.h>
44 #include "contiki.h"
45 #include "dev/i2c.h"
46 #include "dev/grove-gyro.h"
47 #include "lib/sensors.h"
48 #include "dev/watchdog.h"
49 /*---------------------------------------------------------------------------*/
50 #define DEBUG 0
51 #if DEBUG
52 #define PRINTF(...) printf(__VA_ARGS__)
53 #else
54 #define PRINTF(...)
55 #endif
56 /*---------------------------------------------------------------------------*/
57 #define GROVE_GYRO_INT_PORT_BASE GPIO_PORT_TO_BASE(I2C_INT_PORT)
58 #define GROVE_GYRO_INT_PIN_MASK GPIO_PIN_MASK(I2C_INT_PIN)
59 /*---------------------------------------------------------------------------*/
60 static uint8_t enabled;
61 static uint8_t power_mgmt;
62 static uint8_t int_en;
63 /*---------------------------------------------------------------------------*/
64 grove_gyro_values_t gyro_values;
65 /*---------------------------------------------------------------------------*/
66 void (*grove_gyro_int_callback)(uint8_t value);
67 /*---------------------------------------------------------------------------*/
68 static uint16_t
69 grove_gyro_read_reg(uint8_t reg, uint8_t *buf, uint8_t num)
70 {
71  if((buf == NULL) || (num <= 0)) {
72  return GROVE_GYRO_ERROR;
73  }
74 
76  if(i2c_single_send(GROVE_GYRO_ADDR, reg) == I2C_MASTER_ERR_NONE) {
77  if(i2c_burst_receive(GROVE_GYRO_ADDR, buf, num) == I2C_MASTER_ERR_NONE) {
78  return GROVE_GYRO_SUCCESS;
79  }
80  }
81 
82  PRINTF("Gyro: failed to read from sensor\n");
83  return GROVE_GYRO_ERROR;
84 }
85 /*---------------------------------------------------------------------------*/
86 static int
87 grove_gyro_write_reg(uint8_t *buf, uint8_t num)
88 {
89  if((buf == NULL) || (num <= 0)) {
90  PRINTF("Gyro: invalid write values\n");
91  return GROVE_GYRO_ERROR;
92  }
93 
95  if(i2c_burst_send(GROVE_GYRO_ADDR, buf, num) == I2C_MASTER_ERR_NONE) {
96  return GROVE_GYRO_SUCCESS;
97  }
98  return GROVE_GYRO_ERROR;
99 }
100 /*---------------------------------------------------------------------------*/
101 static int
102 grove_gyro_sampdiv(uint8_t value)
103 {
104  uint8_t buf[2];
105  buf[0] = GROVE_GYRO_SMPLRT_DIV;
106  buf[1] = value;
107  if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
108  PRINTF("Gyro: new sampdiv 0x%02X\n", value);
109  return GROVE_GYRO_SUCCESS;
110  }
111  PRINTF("Gyro: failed to set sampdiv\n");
112  return GROVE_GYRO_ERROR;
113 }
114 /*---------------------------------------------------------------------------*/
115 static uint8_t
116 grove_gyro_clear_interrupt(void)
117 {
118  uint8_t aux = 0;
119 
120  /* Clear interrupt */
121  grove_gyro_read_reg(GROVE_GYRO_INT_STATUS, &aux, 1);
122 
123  if(aux & GROVE_GYRO_INT_STATUS_DATA_RDY_MASK) {
124  return GROVE_GYRO_INT_STATUS_DATA_RDY_MASK;
125  }
126 
127  return 0;
128 }
129 /*---------------------------------------------------------------------------*/
130 static int
131 grove_gyro_interrupt(uint8_t value)
132 {
133  uint8_t buf[2];
134  buf[0] = GROVE_GYRO_INT_CFG;
135  buf[1] = value;
136  if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS){
137  PRINTF("Gyro: interrupt cfg 0x%02X\n", value);
138  return GROVE_GYRO_SUCCESS;
139  }
140  PRINTF("Gyro: failed to change interrupt config\n");
141  return GROVE_GYRO_ERROR;
142 }
143 /*---------------------------------------------------------------------------*/
144 static int
145 grove_gyro_reset(void)
146 {
147  uint8_t buf[2];
148  buf[0] = GROVE_GYRO_PWR_MGMT;
149 
150  /* Read the power management status as well to force sync */
151  if(grove_gyro_read_reg(GROVE_GYRO_PWR_MGMT, &power_mgmt, 1) ==
152  GROVE_GYRO_SUCCESS) {
153  PRINTF("Gyro: current power mgmt 0x%02X\n", power_mgmt);
154  buf[1] = power_mgmt + GROVE_GYRO_PWR_MGMT_RESET;
155  if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
156  PRINTF("Gyro: restarted with 0x%02X, now with default values\n", buf[1]);
157  return GROVE_GYRO_SUCCESS;
158  }
159  }
160  PRINTF("Gyro: failed to restart\n");
161  return GROVE_GYRO_ERROR;
162 }
163 /*---------------------------------------------------------------------------*/
164 static int
165 grove_gyro_osc(uint8_t value)
166 {
167  uint8_t buf[2];
168  buf[0] = GROVE_GYRO_PWR_MGMT;
169 
170  /* Read the power management status as well to force sync */
171  if(grove_gyro_read_reg(GROVE_GYRO_PWR_MGMT, &power_mgmt, 1) ==
172  GROVE_GYRO_SUCCESS) {
173  PRINTF("Gyro: current power mgmt 0x%02X\n", power_mgmt);
174  power_mgmt &= ~GROVE_GYRO_PWR_MGMT_CLK_SEL_MASK;
175  buf[1] = power_mgmt + value;
176  if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
177  PRINTF("Gyro: new clock source 0x%02X\n", buf[1]);
178  return GROVE_GYRO_SUCCESS;
179  }
180  }
181  PRINTF("Gyro: failed to change the clock source\n");
182  return GROVE_GYRO_ERROR;
183 }
184 /*---------------------------------------------------------------------------*/
185 static int
186 grove_gyro_power_mgmt(uint8_t value, uint8_t type)
187 {
188  uint8_t buf[2];
189  buf[0] = GROVE_GYRO_PWR_MGMT;
190 
191  if((type != GROVE_GYRO_POWER_ON) && (type != GROVE_GYRO_POWER_OFF)) {
192  PRINTF("Gyro: invalid power command type\n");
193  return GROVE_GYRO_ERROR;
194  }
195 
196  /* Read the power management status as well to force sync */
197  if(grove_gyro_read_reg(GROVE_GYRO_PWR_MGMT, &power_mgmt, 1) ==
198  GROVE_GYRO_SUCCESS) {
199  PRINTF("Gyro: current power mgmt 0x%02X\n", power_mgmt);
200 
201  if(type == GROVE_GYRO_POWER_ON) {
202  power_mgmt &= ~value;
203  } else {
204  power_mgmt |= value;
205  }
206 
207  buf[1] = power_mgmt;
208  if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
209  PRINTF("Gyro: new power management register value 0x%02X\n", power_mgmt);
210 
211  /* Power-up delay */
212  if(type == GROVE_GYRO_POWER_ON) {
213  clock_delay_usec(25000);
214  }
215 
216  return GROVE_GYRO_SUCCESS;
217  }
218  }
219  PRINTF("Gyro: power management fail\n");
220 
221  return GROVE_GYRO_ERROR;
222 }
223 /*---------------------------------------------------------------------------*/
224 static int
225 grove_gyro_dlpf(uint8_t value)
226 {
227  uint8_t buf[2];
228  buf[0] = GROVE_GYRO_DLPF_FS;
229  buf[1] = GROVE_GYRO_DLPF_FS_SEL + value;
230 
231  if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
232  /* Double-check */
233  if(grove_gyro_read_reg(GROVE_GYRO_DLPF_FS, &buf[0], 1) ==
234  GROVE_GYRO_SUCCESS) {
235  if(buf[0] == buf[1]) {
236  PRINTF("Gyro: updated lp/sr 0x%02X\n", buf[0]);
237  return GROVE_GYRO_SUCCESS;
238  } else {
239  PRINTF("Gyro: DLPF register value mismatch\n");
240  return GROVE_GYRO_ERROR;
241  }
242  }
243  }
244 
245  PRINTF("Gyro: failed to change the lp/sr\n");
246  return GROVE_GYRO_ERROR;
247 }
248 /*---------------------------------------------------------------------------*/
249 static uint16_t
250 grove_gyro_convert_to_value(uint16_t val)
251 {
252  uint32_t aux;
253 
254  /* Convert from 2C's to 10's, as we care about º/s negative quantifier doesn't
255  * matter, so we ommit flaging the sign
256  */
257  if(val & 0x8000) {
258  val = (~val + 1);
259  }
260 
261  /* ITG-3200 datasheet: sensitivity 14.375 LSB/(º/s) to get º/s */
262  aux = val * 6956;
263  aux /= 1000;
264 
265  return (uint16_t)aux;
266 }
267 /*---------------------------------------------------------------------------*/
268 static void
269 grove_gyro_convert(uint8_t *buf, uint8_t type)
270 {
271  uint16_t aux;
272 
273  if(type & GROVE_GYRO_X) {
274  aux = (buf[0] << 8) + buf[1];
275  PRINTF("Gyro: X_axis (raw) 0x%02X\n", aux);
276  gyro_values.x = grove_gyro_convert_to_value(aux);
277  }
278 
279  if(type & GROVE_GYRO_Y) {
280  aux = (buf[2] << 8) + buf[3];
281  PRINTF("Gyro: Y_axis (raw) 0x%02X\n", aux);
282  gyro_values.y = grove_gyro_convert_to_value(aux);
283  }
284 
285  if(type & GROVE_GYRO_Z) {
286  aux = (buf[4] << 8) + buf[5];
287  PRINTF("Gyro: Z_axis (raw) 0x%02X\n", aux);
288  gyro_values.z = grove_gyro_convert_to_value(aux);
289  }
290 
291  if(type == GROVE_GYRO_TEMP) {
292  aux = (buf[0] << 8) + buf[1];
293  PRINTF("Gyro: Temp (raw) 0x%02X\n", aux);
294  /* ITG-3200 datasheet: offset -13200, sensitivity 280 LSB/ºC */
295  aux = (aux + 13200) / 28;
296  aux += 350;
297  gyro_values.temp = (int16_t)aux;
298  }
299 }
300 /*---------------------------------------------------------------------------*/
301 static int
302 grove_gyro_read(int type)
303 {
304  uint8_t reg;
305  uint8_t len;
306  uint8_t buf_ptr;
307  uint8_t buf[GROVE_GYRO_MAX_DATA];
308 
309  len = (type == GROVE_GYRO_XYZ) ? GROVE_GYRO_MAX_DATA : 2;
310 
311  switch(type) {
312  case GROVE_GYRO_X:
313  case GROVE_GYRO_XYZ:
314  buf_ptr = 0;
315  reg = GROVE_GYRO_XOUT_H;
316  break;
317  case GROVE_GYRO_Y:
318  buf_ptr = 2;
319  reg = GROVE_GYRO_YOUT_H;
320  break;
321  case GROVE_GYRO_Z:
322  buf_ptr = 4;
323  reg = GROVE_GYRO_ZOUT_H;
324  break;
325  case GROVE_GYRO_TEMP:
326  buf_ptr = 0;
327  reg = GROVE_GYRO_TEMP_OUT_H;
328  break;
329  case GROVE_GYRO_ADDR:
330  buf_ptr = 0;
331  len = 1;
332  reg = GROVE_GYRO_WHO_AM_I;
333  break;
334  default:
335  PRINTF("Gyro: invalid value requested\n");
336  return GROVE_GYRO_ERROR;
337  }
338 
339  if(grove_gyro_read_reg(reg, &buf[buf_ptr], len) == GROVE_GYRO_SUCCESS) {
340  if(type == GROVE_GYRO_ADDR) {
341  PRINTF("Gyro: I2C_addr 0x%02X\n", buf[0]);
342  return buf[0];
343  }
344  grove_gyro_convert(buf, type);
345  return GROVE_GYRO_SUCCESS;
346  }
347 
348  PRINTF("Gyro: failed to change the lp/sr\n");
349  return GROVE_GYRO_ERROR;
350 }
351 /*---------------------------------------------------------------------------*/
352 static int
353 grove_gyro_calibrate(void)
354 {
355  uint8_t i;
356  uint8_t buf[GROVE_GYRO_MAX_DATA];
357  uint8_t power_mgmt_backup;
358  uint32_t x, y, z;
359 
360  /* Disable interrupts */
361  if(int_en) {
362  if(grove_gyro_interrupt(GROVE_GYRO_INT_CFG_DISABLE) == GROVE_GYRO_ERROR) {
363  PRINTF("Gyro: failed to disable the interrupts\n");
364  return GROVE_GYRO_ERROR;
365  }
366  GPIO_DISABLE_INTERRUPT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
367  }
368 
369  /* Turn on the 3-axis, save the current config */
370  if(grove_gyro_read_reg(GROVE_GYRO_PWR_MGMT, &power_mgmt_backup, 1) ==
371  GROVE_GYRO_ERROR) {
372  PRINTF("Gyro: failed to read power mgmt config\n");
373  return GROVE_GYRO_ERROR;
374  }
375 
376  if(grove_gyro_power_mgmt(GROVE_GYRO_ALL, GROVE_GYRO_POWER_ON) ==
377  GROVE_GYRO_ERROR) {
378  PRINTF("Gyro: failed to bring sensor up\n");
379  return GROVE_GYRO_ERROR;
380  }
381 
382  x = 0;
383  y = 0;
384  z = 0;
385 
386  for (i = 0; i < GROVE_GYRO_CALIB_SAMPLES; i++){
387  clock_delay_usec(GROVE_GYRO_CALIB_TIME_US);
389  if(grove_gyro_read_reg(GROVE_GYRO_XOUT_H, buf, GROVE_GYRO_MAX_DATA) ==
390  GROVE_GYRO_SUCCESS) {
391  x += (buf[0] << 8) + buf[1];
392  y += (buf[2] << 8) + buf[3];
393  z += (buf[4] << 8) + buf[5];
394  }
395  }
396 
397  gyro_values.x_offset = ABS(x)/GROVE_GYRO_CALIB_SAMPLES;
398  gyro_values.y_offset = ABS(y)/GROVE_GYRO_CALIB_SAMPLES;
399  gyro_values.z_offset = ABS(z)/GROVE_GYRO_CALIB_SAMPLES;
400 
401  PRINTF("Gyro: x_offset (RAW) 0x%02X\n", gyro_values.x_offset);
402  PRINTF("Gyro: y_offset (RAW) 0x%02X\n", gyro_values.y_offset);
403  PRINTF("Gyro: z_offset (RAW) 0x%02X\n", gyro_values.z_offset);
404 
405  gyro_values.x_offset = grove_gyro_convert_to_value(gyro_values.x_offset);
406  gyro_values.y_offset = grove_gyro_convert_to_value(gyro_values.y_offset);
407  gyro_values.z_offset = grove_gyro_convert_to_value(gyro_values.z_offset);
408 
409  PRINTF("Gyro: x_offset (converted) %d\n", gyro_values.x_offset);
410  PRINTF("Gyro: y_offset (converted) %d\n", gyro_values.y_offset);
411  PRINTF("Gyro: z_offset (converted) %d\n", gyro_values.z_offset);
412 
413  /* Cleaning up */
414  buf[0] = GROVE_GYRO_PWR_MGMT;
415  buf[1] = power_mgmt_backup;
416 
417  if(grove_gyro_write_reg(&buf[0], 2) != GROVE_GYRO_SUCCESS) {
418  PRINTF("Gyro: failed restoring power mgmt (0x%02X)\n", power_mgmt_backup);
419  return GROVE_GYRO_ERROR;
420  }
421 
422  if(int_en) {
423  if(grove_gyro_interrupt(GROVE_GYRO_INT_CFG_RAW_READY_EN +
424  GROVE_GYRO_INT_CFG_LATCH_EN) == GROVE_GYRO_ERROR) {
425  PRINTF("Gyro: failed to enable the interrupt\n");
426  return GROVE_GYRO_ERROR;
427  }
428 
429  GPIO_ENABLE_INTERRUPT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
430  }
431 
432  return GROVE_GYRO_SUCCESS;
433 }
434 /*---------------------------------------------------------------------------*/
435 PROCESS(grove_gyro_int_process, "Grove gyroscope interrupt process handler");
436 /*---------------------------------------------------------------------------*/
437 PROCESS_THREAD(grove_gyro_int_process, ev, data)
438 {
440  PROCESS_BEGIN();
441 
442  static uint8_t axis_to_read = 0;
443 
444  while(1) {
445  PROCESS_YIELD_UNTIL(ev == PROCESS_EVENT_POLL);
446  if(grove_gyro_clear_interrupt() == GROVE_GYRO_INT_STATUS_DATA_RDY_MASK) {
447 
448  axis_to_read += (power_mgmt & GROVE_GYRO_X) ? 0: GROVE_GYRO_X;
449  axis_to_read += (power_mgmt & GROVE_GYRO_Y) ? 0: GROVE_GYRO_Y;
450  axis_to_read += (power_mgmt & GROVE_GYRO_Z) ? 0: GROVE_GYRO_Z;
451 
452  if(grove_gyro_read(axis_to_read) == GROVE_GYRO_SUCCESS) {
453  grove_gyro_int_callback(GROVE_GYRO_SUCCESS);
454  }
455  }
456  }
457  PROCESS_END();
458 }
459 /*---------------------------------------------------------------------------*/
460 static void
461 grove_gyro_interrupt_handler(uint8_t port, uint8_t pin)
462 {
463  process_poll(&grove_gyro_int_process);
464 }
465 /*---------------------------------------------------------------------------*/
466 static int
467 value(int type)
468 {
469  if(!enabled) {
470  PRINTF("Gyro: sensor not started\n");
471  return GROVE_GYRO_ERROR;
472  }
473 
474  if((type != GROVE_GYRO_X) && (type != GROVE_GYRO_Y) &&
475  (type != GROVE_GYRO_Z) && (type != GROVE_GYRO_XYZ) &&
476  (type != GROVE_GYRO_TEMP) && (type != GROVE_GYRO_ADDR)) {
477  PRINTF("Gyro: invalid value requested 0x%02X\n", type);
478  return GROVE_GYRO_ERROR;
479  }
480 
481  if((type != GROVE_GYRO_TEMP) && (type != GROVE_GYRO_ADDR) &&
482  (type & power_mgmt)) {
483  PRINTF("Gyro: axis not enabled (0x%02X vs 0x%02X)\n", power_mgmt, type);
484  return GROVE_GYRO_ERROR;
485  }
486 
487  return grove_gyro_read(type);
488 }
489 /*---------------------------------------------------------------------------*/
490 static int
491 configure(int type, int value)
492 {
493  if((type != GROVE_GYRO_ACTIVE) && (type != GROVE_GYRO_SAMPLE_RATE) &&
494  (type != GROVE_GYRO_SAMPLE_RATE_DIVIDER) && (type != GROVE_GYRO_POWER_ON) &&
495  (type != GROVE_GYRO_POWER_OFF) && (type != GROVE_GYRO_DATA_INTERRUPT) &&
496  (type != GROVE_GYRO_CALIBRATE_ZERO)) {
497  PRINTF("Gyro: option not supported\n");
498  return GROVE_GYRO_ERROR;
499  }
500 
501  switch(type) {
502  case GROVE_GYRO_ACTIVE:
503  if(value) {
504  i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN,
505  I2C_SCL_FAST_BUS_SPEED);
506 
507  /* Initialize the data structure values */
508  gyro_values.x = 0;
509  gyro_values.y = 0;
510  gyro_values.z = 0;
511  gyro_values.temp = 0;
512  gyro_values.x_offset = 0;
513  gyro_values.y_offset = 0;
514  gyro_values.z_offset = 0;
515 
516  /* Make sure the sensor is on */
517  if(grove_gyro_power_mgmt(GROVE_GYRO_ALL, GROVE_GYRO_POWER_ON) !=
518  GROVE_GYRO_SUCCESS) {
519  PRINTF("Gyro: failed to power on the sensor\n");
520  return GROVE_GYRO_ERROR;
521  }
522 
523  /* Reset and configure as default with internal oscillator, 8KHz @ 2000
524  * degrees/s, no divider (full scale)
525  */
526  if(grove_gyro_reset() == GROVE_GYRO_SUCCESS) {
527  if(grove_gyro_osc(GROVE_GYRO_DEFAULT_OSC) == GROVE_GYRO_SUCCESS) {
528  if(grove_gyro_dlpf(GROVE_GYRO_DLPF_FS_CGF_8KHZ_LP256HZ) ==
529  GROVE_GYRO_SUCCESS) {
530  PRINTF("Gyro: started and configured\n");
531  /* Disable interrupts as default */
532  if(grove_gyro_interrupt(GROVE_GYRO_INT_CFG_DISABLE) ==
533  GROVE_GYRO_SUCCESS) {
534  PRINTF("Gyro: interrupts disabled\n");
535  /* And finally put the device in SLEEP mode, set also X, Y and Z
536  * in stand-by mode, whenever an axis is not used it should stay
537  * in this state to save power
538  */
539  if(grove_gyro_power_mgmt(GROVE_GYRO_ALL, GROVE_GYRO_POWER_OFF) ==
540  GROVE_GYRO_SUCCESS) {
541  enabled = 1;
542  PRINTF("Gyro: axis and gyroscope in low-power mode now\n");
543 
544  return GROVE_GYRO_SUCCESS;
545  }
546  }
547  }
548  }
549  }
550  return GROVE_GYRO_ERROR;
551 
552  } else {
553  enabled = 0;
554  int_en = 0;
555  GPIO_DISABLE_INTERRUPT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
556  grove_gyro_int_callback = NULL;
557  if(grove_gyro_interrupt(GROVE_GYRO_INT_CFG_DISABLE) ==
558  GROVE_GYRO_SUCCESS) {
559  return grove_gyro_power_mgmt(GROVE_GYRO_ALL, GROVE_GYRO_POWER_OFF);
560  }
561  PRINTF("Gyro: hw interrupt disabled but failed to disable sensor\n");
562  return GROVE_GYRO_ERROR;
563  }
564 
565  if(!enabled) {
566  PRINTF("Gyro: sensor not started\n");
567  return GROVE_GYRO_ERROR;
568  }
569 
570  case GROVE_GYRO_DATA_INTERRUPT:
571 
572  if(!value) {
573 
574  /* Ensure the GPIO doesn't generate more interrupts, this may affect others
575  * I2C digital sensors using the bus and sharing this pin, so an user may
576  * comment the line below
577  */
578  int_en = 0;
579  GPIO_DISABLE_INTERRUPT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
580  return grove_gyro_interrupt(GROVE_GYRO_INT_CFG_DISABLE);
581  }
582 
583  /* Enable interrupt and latch the pin until cleared */
584  if(grove_gyro_interrupt(GROVE_GYRO_INT_CFG_RAW_READY_EN +
585  GROVE_GYRO_INT_CFG_LATCH_EN) == GROVE_GYRO_ERROR) {
586  PRINTF("Gyro: failed to enable the interrupt\n");
587  return GROVE_GYRO_ERROR;
588  }
589 
590  /* Default register configuration is active high, push-pull */
591  GPIO_SOFTWARE_CONTROL(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
592  GPIO_SET_INPUT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
593  GPIO_DETECT_EDGE(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
594  GPIO_TRIGGER_SINGLE_EDGE(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
595  GPIO_DETECT_FALLING(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
596  gpio_register_callback(grove_gyro_interrupt_handler, I2C_INT_PORT,
597  I2C_INT_PIN);
598 
599  /* Spin process until an interrupt is received */
600  process_start(&grove_gyro_int_process, NULL);
601 
602  /* Enable interrupts */
603  int_en = 1;
604  GPIO_ENABLE_INTERRUPT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
605  ioc_set_over(I2C_INT_PORT, I2C_INT_PIN, IOC_OVERRIDE_PUE);
606  nvic_interrupt_enable(I2C_INT_VECTOR);
607 
608  PRINTF("Gyro: Data interrupt configured\n");
609  return GROVE_GYRO_SUCCESS;
610 
611  case GROVE_GYRO_SAMPLE_RATE:
612  if((value < GROVE_GYRO_DLPF_FS_CGF_8KHZ_LP256HZ) ||
613  (value > GROVE_GYRO_DLPF_FS_CGF_1KHZ_LP5HZ)) {
614  PRINTF("Gyro: invalid sample rate/filter configuration\n");
615  return GROVE_GYRO_ERROR;
616  }
617  return grove_gyro_dlpf(value);
618 
619  case GROVE_GYRO_SAMPLE_RATE_DIVIDER:
620  if((value < 0) && (value > 0xFF)) {
621  PRINTF("Gyro: invalid sampling rate div, it must be an 8-bit value\n");
622  return GROVE_GYRO_ERROR;
623  }
624  return grove_gyro_sampdiv((uint8_t)value);
625 
626  case GROVE_GYRO_POWER_ON:
627  case GROVE_GYRO_POWER_OFF:
628  /* We accept mask values to enable more than one axis at the same time */
629  if((value < GROVE_GYRO_Z) || (value > GROVE_GYRO_ALL)) {
630  PRINTF("Gyro: invalid power management setting\n");
631  return GROVE_GYRO_ERROR;
632  }
633  return grove_gyro_power_mgmt(value, type);
634 
635  case GROVE_GYRO_CALIBRATE_ZERO:
636  return grove_gyro_calibrate();
637 
638  default:
639  return GROVE_GYRO_ERROR;
640  }
641 
642  return GROVE_GYRO_ERROR;
643 }
644 /*---------------------------------------------------------------------------*/
645 SENSORS_SENSOR(grove_gyro, GROVE_GYRO_STRING, value, configure, NULL);
646 /*---------------------------------------------------------------------------*/
647 /** @} */
#define GPIO_TRIGGER_SINGLE_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on single edge (controlled by G...
Definition: gpio.h:178
void process_poll(struct process *p)
Request a process to be polled.
Definition: process.c:371
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:202
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
Definition: gpio.h:93
#define IOC_OVERRIDE_PUE
Pull Up Enable.
Definition: ioc.h:223
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
Definition: gpio.h:155
void i2c_master_enable(void)
Enable master I2C module.
Definition: i2c.c:91
#define PROCESS_END()
Define the end of a process.
Definition: process.h:131
#define PROCESS(name, strname)
Declare a process.
Definition: process.h:307
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
Definition: process.h:273
#define GPIO_DETECT_FALLING(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to trigger an interrupt on falling edge.
Definition: gpio.h:194
void i2c_init(uint8_t port_sda, uint8_t pin_sda, uint8_t port_scl, uint8_t pin_scl, uint32_t bus_speed)
Initialize the I2C peripheral and pins.
Definition: i2c.c:49
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
Definition: process.h:254
uint8_t i2c_burst_send(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to send multiple bytes to a slave.
Definition: i2c.c:188
#define NULL
The null pointer.
uint8_t i2c_burst_receive(uint8_t slave_addr, uint8_t *data, uint8_t len)
Perform all operations to receive multiple bytes from a slave.
Definition: i2c.c:218
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
Definition: i2c.c:159
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
Definition: gpio.h:259
void watchdog_periodic(void)
Writes the WDT clear sequence.
Definition: watchdog.c:64
void process_start(struct process *p, process_data_t data)
Start a process.
Definition: process.c:99
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
Definition: process.h:178
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
Definition: nvic.c:64
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
Definition: gpio.h:210
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
Definition: ioc.c:54
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
Definition: gpio.c:56
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Definition: clock.c:94
Grove 3-axis gyroscope header file.
#define PROCESS_BEGIN()
Define the beginning of a process.
Definition: process.h:120