47 #include "lib/sensors.h"
48 #include "dev/watchdog.h"
52 #define PRINTF(...) printf(__VA_ARGS__)
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)
60 static uint8_t enabled;
61 static uint8_t power_mgmt;
62 static uint8_t int_en;
64 grove_gyro_values_t gyro_values;
66 void (*grove_gyro_int_callback)(uint8_t value);
69 grove_gyro_read_reg(uint8_t reg, uint8_t *buf, uint8_t num)
71 if((buf ==
NULL) || (num <= 0)) {
72 return GROVE_GYRO_ERROR;
78 return GROVE_GYRO_SUCCESS;
82 PRINTF(
"Gyro: failed to read from sensor\n");
83 return GROVE_GYRO_ERROR;
87 grove_gyro_write_reg(uint8_t *buf, uint8_t num)
89 if((buf ==
NULL) || (num <= 0)) {
90 PRINTF(
"Gyro: invalid write values\n");
91 return GROVE_GYRO_ERROR;
95 if(
i2c_burst_send(GROVE_GYRO_ADDR, buf, num) == I2C_MASTER_ERR_NONE) {
96 return GROVE_GYRO_SUCCESS;
98 return GROVE_GYRO_ERROR;
102 grove_gyro_sampdiv(uint8_t value)
105 buf[0] = GROVE_GYRO_SMPLRT_DIV;
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;
111 PRINTF(
"Gyro: failed to set sampdiv\n");
112 return GROVE_GYRO_ERROR;
116 grove_gyro_clear_interrupt(
void)
121 grove_gyro_read_reg(GROVE_GYRO_INT_STATUS, &aux, 1);
123 if(aux & GROVE_GYRO_INT_STATUS_DATA_RDY_MASK) {
124 return GROVE_GYRO_INT_STATUS_DATA_RDY_MASK;
131 grove_gyro_interrupt(uint8_t value)
134 buf[0] = GROVE_GYRO_INT_CFG;
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;
140 PRINTF(
"Gyro: failed to change interrupt config\n");
141 return GROVE_GYRO_ERROR;
145 grove_gyro_reset(
void)
148 buf[0] = GROVE_GYRO_PWR_MGMT;
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;
160 PRINTF(
"Gyro: failed to restart\n");
161 return GROVE_GYRO_ERROR;
165 grove_gyro_osc(uint8_t value)
168 buf[0] = GROVE_GYRO_PWR_MGMT;
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;
181 PRINTF(
"Gyro: failed to change the clock source\n");
182 return GROVE_GYRO_ERROR;
186 grove_gyro_power_mgmt(uint8_t value, uint8_t type)
189 buf[0] = GROVE_GYRO_PWR_MGMT;
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;
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);
201 if(type == GROVE_GYRO_POWER_ON) {
202 power_mgmt &= ~value;
208 if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
209 PRINTF(
"Gyro: new power management register value 0x%02X\n", power_mgmt);
212 if(type == GROVE_GYRO_POWER_ON) {
216 return GROVE_GYRO_SUCCESS;
219 PRINTF(
"Gyro: power management fail\n");
221 return GROVE_GYRO_ERROR;
225 grove_gyro_dlpf(uint8_t value)
228 buf[0] = GROVE_GYRO_DLPF_FS;
229 buf[1] = GROVE_GYRO_DLPF_FS_SEL + value;
231 if(grove_gyro_write_reg(buf, 2) == GROVE_GYRO_SUCCESS) {
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;
239 PRINTF(
"Gyro: DLPF register value mismatch\n");
240 return GROVE_GYRO_ERROR;
245 PRINTF(
"Gyro: failed to change the lp/sr\n");
246 return GROVE_GYRO_ERROR;
250 grove_gyro_convert_to_value(uint16_t val)
265 return (uint16_t)aux;
269 grove_gyro_convert(uint8_t *buf, uint8_t type)
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);
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);
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);
291 if(type == GROVE_GYRO_TEMP) {
292 aux = (buf[0] << 8) + buf[1];
293 PRINTF(
"Gyro: Temp (raw) 0x%02X\n", aux);
295 aux = (aux + 13200) / 28;
297 gyro_values.temp = (int16_t)aux;
302 grove_gyro_read(
int type)
307 uint8_t buf[GROVE_GYRO_MAX_DATA];
309 len = (type == GROVE_GYRO_XYZ) ? GROVE_GYRO_MAX_DATA : 2;
315 reg = GROVE_GYRO_XOUT_H;
319 reg = GROVE_GYRO_YOUT_H;
323 reg = GROVE_GYRO_ZOUT_H;
325 case GROVE_GYRO_TEMP:
327 reg = GROVE_GYRO_TEMP_OUT_H;
329 case GROVE_GYRO_ADDR:
332 reg = GROVE_GYRO_WHO_AM_I;
335 PRINTF(
"Gyro: invalid value requested\n");
336 return GROVE_GYRO_ERROR;
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]);
344 grove_gyro_convert(buf, type);
345 return GROVE_GYRO_SUCCESS;
348 PRINTF(
"Gyro: failed to change the lp/sr\n");
349 return GROVE_GYRO_ERROR;
353 grove_gyro_calibrate(
void)
356 uint8_t buf[GROVE_GYRO_MAX_DATA];
357 uint8_t power_mgmt_backup;
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;
370 if(grove_gyro_read_reg(GROVE_GYRO_PWR_MGMT, &power_mgmt_backup, 1) ==
372 PRINTF(
"Gyro: failed to read power mgmt config\n");
373 return GROVE_GYRO_ERROR;
376 if(grove_gyro_power_mgmt(GROVE_GYRO_ALL, GROVE_GYRO_POWER_ON) ==
378 PRINTF(
"Gyro: failed to bring sensor up\n");
379 return GROVE_GYRO_ERROR;
386 for (i = 0; i < GROVE_GYRO_CALIB_SAMPLES; i++){
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];
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;
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);
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);
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);
414 buf[0] = GROVE_GYRO_PWR_MGMT;
415 buf[1] = power_mgmt_backup;
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;
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;
432 return GROVE_GYRO_SUCCESS;
435 PROCESS(grove_gyro_int_process,
"Grove gyroscope interrupt process handler");
442 static uint8_t axis_to_read = 0;
446 if(grove_gyro_clear_interrupt() == GROVE_GYRO_INT_STATUS_DATA_RDY_MASK) {
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;
452 if(grove_gyro_read(axis_to_read) == GROVE_GYRO_SUCCESS) {
453 grove_gyro_int_callback(GROVE_GYRO_SUCCESS);
461 grove_gyro_interrupt_handler(uint8_t port, uint8_t pin)
470 PRINTF(
"Gyro: sensor not started\n");
471 return GROVE_GYRO_ERROR;
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;
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;
487 return grove_gyro_read(type);
491 configure(
int type,
int value)
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;
502 case GROVE_GYRO_ACTIVE:
504 i2c_init(I2C_SDA_PORT, I2C_SDA_PIN, I2C_SCL_PORT, I2C_SCL_PIN,
505 I2C_SCL_FAST_BUS_SPEED);
511 gyro_values.temp = 0;
512 gyro_values.x_offset = 0;
513 gyro_values.y_offset = 0;
514 gyro_values.z_offset = 0;
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;
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");
532 if(grove_gyro_interrupt(GROVE_GYRO_INT_CFG_DISABLE) ==
533 GROVE_GYRO_SUCCESS) {
534 PRINTF(
"Gyro: interrupts disabled\n");
539 if(grove_gyro_power_mgmt(GROVE_GYRO_ALL, GROVE_GYRO_POWER_OFF) ==
540 GROVE_GYRO_SUCCESS) {
542 PRINTF(
"Gyro: axis and gyroscope in low-power mode now\n");
544 return GROVE_GYRO_SUCCESS;
550 return GROVE_GYRO_ERROR;
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);
561 PRINTF(
"Gyro: hw interrupt disabled but failed to disable sensor\n");
562 return GROVE_GYRO_ERROR;
566 PRINTF(
"Gyro: sensor not started\n");
567 return GROVE_GYRO_ERROR;
570 case GROVE_GYRO_DATA_INTERRUPT:
580 return grove_gyro_interrupt(GROVE_GYRO_INT_CFG_DISABLE);
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;
592 GPIO_SET_INPUT(GROVE_GYRO_INT_PORT_BASE, GROVE_GYRO_INT_PIN_MASK);
608 PRINTF(
"Gyro: Data interrupt configured\n");
609 return GROVE_GYRO_SUCCESS;
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;
617 return grove_gyro_dlpf(value);
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;
624 return grove_gyro_sampdiv((uint8_t)value);
626 case GROVE_GYRO_POWER_ON:
627 case GROVE_GYRO_POWER_OFF:
629 if((value < GROVE_GYRO_Z) || (value > GROVE_GYRO_ALL)) {
630 PRINTF(
"Gyro: invalid power management setting\n");
631 return GROVE_GYRO_ERROR;
633 return grove_gyro_power_mgmt(value, type);
635 case GROVE_GYRO_CALIBRATE_ZERO:
636 return grove_gyro_calibrate();
639 return GROVE_GYRO_ERROR;
642 return GROVE_GYRO_ERROR;
645 SENSORS_SENSOR(grove_gyro, GROVE_GYRO_STRING, value, configure,
NULL);
#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...
void process_poll(struct process *p)
Request a process to be polled.
#define GPIO_ENABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Enable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
#define GPIO_SET_INPUT(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to input.
#define IOC_OVERRIDE_PUE
Pull Up Enable.
#define GPIO_DETECT_EDGE(PORT_BASE, PIN_MASK)
Set pins with PIN_MASK of port with PORT_BASE to detect edge.
void i2c_master_enable(void)
Enable master I2C module.
#define PROCESS_END()
Define the end of a process.
#define PROCESS(name, strname)
Declare a process.
#define PROCESS_THREAD(name, ev, data)
Define the body of a process.
#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.
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.
#define PROCESS_EXITHANDLER(handler)
Specify an action when a process exits.
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.
#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.
uint8_t i2c_single_send(uint8_t slave_addr, uint8_t data)
Perform all operations to send a byte to a slave.
#define GPIO_SOFTWARE_CONTROL(PORT_BASE, PIN_MASK)
Configure the pin to be software controlled with PIN_MASK of port with PORT_BASE. ...
void watchdog_periodic(void)
Writes the WDT clear sequence.
void process_start(struct process *p, process_data_t data)
Start a process.
#define PROCESS_YIELD_UNTIL(c)
Yield the currently running process until a condition occurs.
void nvic_interrupt_enable(uint32_t intr)
Enables interrupt intr.
#define GPIO_DISABLE_INTERRUPT(PORT_BASE, PIN_MASK)
Disable interrupt triggering for pins with PIN_MASK of port with PORT_BASE.
void ioc_set_over(uint8_t port, uint8_t pin, uint8_t over)
Set Port:Pin override function.
void gpio_register_callback(gpio_callback_t f, uint8_t port, uint8_t pin)
Register GPIO callback.
void clock_delay_usec(uint16_t dt)
Delay a given number of microseconds.
Grove 3-axis gyroscope header file.
#define PROCESS_BEGIN()
Define the beginning of a process.