diff options
| author | Arda <[email protected]> | 2015-03-10 12:01:25 +0800 |
|---|---|---|
| committer | Arda <[email protected]> | 2015-03-10 12:01:25 +0800 |
| commit | 4a9c3fae2900da71cdf026063679d2c25f266fd7 (patch) | |
| tree | 2fba8aec09a671cc36d281365351003a988eb57d /components/drivers | |
| parent | 5fe489a3949cdbb947d3c719a7ef958a37e8d826 (diff) | |
| parent | 89ceb7dc27895225bc221d22c035d5cc8802a256 (diff) | |
Merge pull request #3 from RT-Thread/master
sync with official source
Diffstat (limited to 'components/drivers')
| -rw-r--r-- | components/drivers/include/drivers/pin.h | 79 | ||||
| -rw-r--r-- | components/drivers/include/rtdevice.h | 4 | ||||
| -rw-r--r-- | components/drivers/misc/SConscript | 14 | ||||
| -rw-r--r-- | components/drivers/misc/pin.c | 118 | ||||
| -rw-r--r-- | components/drivers/sensors/SConscript | 9 | ||||
| -rw-r--r-- | components/drivers/sensors/bmi055_sensor.cpp | 455 | ||||
| -rw-r--r-- | components/drivers/sensors/bmi055_sensor.h | 338 | ||||
| -rw-r--r-- | components/drivers/sensors/mpu6050_sensor.cpp | 462 | ||||
| -rw-r--r-- | components/drivers/sensors/mpu6050_sensor.h | 193 | ||||
| -rw-r--r-- | components/drivers/sensors/sensor.cpp | 169 | ||||
| -rw-r--r-- | components/drivers/sensors/sensor.h | 181 | ||||
| -rw-r--r-- | components/drivers/serial/serial.c | 3 | ||||
| -rw-r--r-- | components/drivers/src/ringbuffer.c | 10 |
13 files changed, 1961 insertions, 74 deletions
diff --git a/components/drivers/include/drivers/pin.h b/components/drivers/include/drivers/pin.h new file mode 100644 index 0000000000..704114cf99 --- /dev/null +++ b/components/drivers/include/drivers/pin.h @@ -0,0 +1,79 @@ +/* + * File : pin.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-20 Bernard the first version + */ + +#ifndef PIN_H__ +#define PIN_H__ + +#include <rtthread.h> +#include <rtdevice.h> + +#ifdef __cplusplus +extern "C" { +#endif + +/* pin device and operations for RT-Thread */ +struct rt_device_pin +{ + struct rt_device parent; + const struct rt_pin_ops *ops; +}; + +#define PIN_LOW 0x00 +#define PIN_HIGH 0x01 + +#define PIN_MODE_OUTPUT 0x00 +#define PIN_MODE_INPUT 0x01 +#define PIN_MODE_INPUT_PULLUP 0x02 + +struct rt_device_pin_mode +{ + rt_uint16_t pin; + rt_uint16_t mode; +}; +struct rt_device_pin_status +{ + rt_uint16_t pin; + rt_uint16_t status; +}; + +struct rt_pin_ops +{ + void (*pin_mode)(struct rt_device *device, rt_base_t pin, rt_base_t mode); + void (*pin_write)(struct rt_device *device, rt_base_t pin, rt_base_t value); + int (*pin_read)(struct rt_device *device, rt_base_t pin); + + /* TODO: add GPIO interrupt */ +}; + +int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data); + +void rt_pin_mode(rt_base_t pin, rt_base_t mode); +void rt_pin_write(rt_base_t pin, rt_base_t value); +int rt_pin_read(rt_base_t pin); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/include/rtdevice.h b/components/drivers/include/rtdevice.h index dc9761032e..bb01da2d12 100644 --- a/components/drivers/include/rtdevice.h +++ b/components/drivers/include/rtdevice.h @@ -358,5 +358,9 @@ rt_inline void rt_work_init(struct rt_work* work, void (*work_func)(struct rt_wo #include "drivers/watchdog.h" #endif +#ifdef RT_USING_PIN +#include "drivers/pin.h" +#endif + #endif /* __RT_DEVICE_H__ */ diff --git a/components/drivers/misc/SConscript b/components/drivers/misc/SConscript new file mode 100644 index 0000000000..7f269d4ee9 --- /dev/null +++ b/components/drivers/misc/SConscript @@ -0,0 +1,14 @@ +from building import * + +cwd = GetCurrentDir() +src = [] +CPPPATH = [cwd + '/../include'] +group = [] + +if GetDepend(['RT_USING_PIN']): + src = src + ['pin.c'] + +if len(src): + group = DefineGroup('DeviceDrivers', src, depend = [''], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/misc/pin.c b/components/drivers/misc/pin.c new file mode 100644 index 0000000000..d83c3d2f03 --- /dev/null +++ b/components/drivers/misc/pin.c @@ -0,0 +1,118 @@ +/* + * File : pin.c + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2015, RT-Thread Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Change Logs: + * Date Author Notes + * 2015-01-20 Bernard the first version + */ + +#include <drivers/pin.h> + +#ifdef RT_USING_FINSH +#include <finsh.h> +#endif + +static struct rt_device_pin _hw_pin; +static rt_size_t _pin_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +{ + struct rt_device_pin_status *status; + struct rt_device_pin *pin = (struct rt_device_pin *)dev; + + /* check parameters */ + RT_ASSERT(pin != RT_NULL); + + status = (struct rt_device_pin_status *) buffer; + if (status == RT_NULL || size != sizeof(*status)) return 0; + + status->status = pin->ops->pin_read(dev, status->pin); + return size; +} + +static rt_size_t _pin_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +{ + struct rt_device_pin_status *status; + struct rt_device_pin *pin = (struct rt_device_pin *)dev; + + /* check parameters */ + RT_ASSERT(pin != RT_NULL); + + status = (struct rt_device_pin_status *) buffer; + if (status == RT_NULL || size != sizeof(*status)) return 0; + + pin->ops->pin_write(dev, (rt_base_t)status->pin, (rt_base_t)status->status); + + return size; +} + +static rt_err_t _pin_control(rt_device_t dev, rt_uint8_t cmd, void *args) +{ + struct rt_device_pin_mode *mode; + struct rt_device_pin *pin = (struct rt_device_pin *)dev; + + /* check parameters */ + RT_ASSERT(pin != RT_NULL); + + mode = (struct rt_device_pin_mode *) args; + if (mode == RT_NULL) return -RT_ERROR; + + pin->ops->pin_mode(dev, (rt_base_t)mode->pin, (rt_base_t)mode->mode); + + return 0; +} + +int rt_device_pin_register(const char *name, const struct rt_pin_ops *ops, void *user_data) +{ + _hw_pin.parent.type = RT_Device_Class_Miscellaneous; + _hw_pin.parent.rx_indicate = RT_NULL; + _hw_pin.parent.tx_complete = RT_NULL; + + _hw_pin.parent.init = RT_NULL; + _hw_pin.parent.open = RT_NULL; + _hw_pin.parent.close = RT_NULL; + _hw_pin.parent.read = _pin_read; + _hw_pin.parent.write = _pin_write; + _hw_pin.parent.control = _pin_control; + + _hw_pin.ops = ops; + _hw_pin.parent.user_data = user_data; + + /* register a character device */ + rt_device_register(&_hw_pin.parent, "pin", RT_DEVICE_FLAG_RDWR); + + return 0; +} + +/* RT-Thread Hardware PIN APIs */ +void rt_pin_mode(rt_base_t pin, rt_base_t mode) +{ + _hw_pin.ops->pin_mode(&_hw_pin.parent, pin, mode); +} +FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_mode, pinMode, set hardware pin mode); + +void rt_pin_write(rt_base_t pin, rt_base_t value) +{ + _hw_pin.ops->pin_write(&_hw_pin.parent, pin, value); +} +FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_write, pinWrite, write value to hardware pin); + +int rt_pin_read(rt_base_t pin) +{ + return _hw_pin.ops->pin_read(&_hw_pin.parent, pin); +} +FINSH_FUNCTION_EXPORT_ALIAS(rt_pin_read, pinRead, read status from hardware pin); diff --git a/components/drivers/sensors/SConscript b/components/drivers/sensors/SConscript index 14a7cd2450..db409cfd2b 100644 --- a/components/drivers/sensors/SConscript +++ b/components/drivers/sensors/SConscript @@ -3,10 +3,15 @@ from building import * cwd = GetCurrentDir() -src = Glob('*.c') + Glob('*.cpp') +src = ['sensor.cpp'] CPPPATH = [cwd, cwd + '/../include'] +if GetDepend('SENSOR_USING_MPU6050') and GetDepend('RT_USING_I2C'): + src += ['mpu6050_sensor.cpp']; + +if GetDepend('SENSOR_USING_BMI055') and GetDepend('RT_USING_I2C'): + src += ['bmi055_sensor.cpp'] + group = DefineGroup('Sensors', src, depend = ['RT_USING_SENSOR', 'RT_USING_DEVICE'], CPPPATH = CPPPATH) Return('group') - diff --git a/components/drivers/sensors/bmi055_sensor.cpp b/components/drivers/sensors/bmi055_sensor.cpp new file mode 100644 index 0000000000..705895f368 --- /dev/null +++ b/components/drivers/sensors/bmi055_sensor.cpp @@ -0,0 +1,455 @@ +/* + * File : bmi055_sensor.cpp + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2014, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2015-1-11 RT_learning the first version + */ + +#include <string.h> +#include <stdio.h> +#include <rtdevice.h> +#include "bmi055_sensor.h" + + +const static sensor_t _BMI055_sensor[] = +{ + { + .name = "Accelerometer", + .vendor = "Bosch", + .version = sizeof(sensor_t), + .handle = 0, + .type = SENSOR_TYPE_ACCELEROMETER, + .maxRange = SENSOR_ACCEL_RANGE_16G, + .resolution = 1.0f, + .power = 0.5f, + .minDelay = 10000, + .fifoReservedEventCount = 0, + .fifoMaxEventCount = 64, + }, + { + .name = "Gyroscope", + .vendor = "Bosch", + .version = sizeof(sensor_t), + .handle = 0, + .type = SENSOR_TYPE_GYROSCOPE, + .maxRange = SENSOR_GYRO_RANGE_2000DPS, + .resolution = 1.0f, + .power = 0.5f, + .minDelay = 10000, + .fifoReservedEventCount = 0, + .fifoMaxEventCount = 64, + } +}; + +BMI055::BMI055(int sensor_type, const char* iic_bus, int addr) + : SensorBase(sensor_type) +{ + this->i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(iic_bus); + if (this->i2c_bus == NULL) + { + printf("BMI055: No IIC device:%s\n", iic_bus); + return; + } + + this->i2c_addr = addr; + + /* register to sensor manager */ + SensorManager::registerSensor(this); +} + +int BMI055::read_reg(rt_uint8_t reg, rt_uint8_t *value) +{ + struct rt_i2c_msg msgs[2]; + + msgs[0].addr = this->i2c_addr; + msgs[0].flags = RT_I2C_WR; + msgs[0].buf = ® + msgs[0].len = 1; + + msgs[1].addr = this->i2c_addr; + msgs[1].flags = RT_I2C_RD; /* Read from slave */ + msgs[1].buf = (rt_uint8_t *)value; + msgs[1].len = 1; + + if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) + return RT_EOK; + + return -RT_ERROR; +} + +int BMI055::read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size) +{ + struct rt_i2c_msg msgs[2]; + + msgs[0].addr = this->i2c_addr; + msgs[0].flags = RT_I2C_WR; + msgs[0].buf = ® + msgs[0].len = 1; + + msgs[1].addr = this->i2c_addr; + msgs[1].flags = RT_I2C_RD; /* Read from slave */ + msgs[1].buf = (rt_uint8_t *)value; + msgs[1].len = size; + + if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) + return RT_EOK; + + return -RT_ERROR; +} + +int BMI055::write_reg(rt_uint8_t reg, rt_uint8_t value) +{ + struct rt_i2c_msg msgs[2]; + + msgs[0].addr = this->i2c_addr; + msgs[0].flags = RT_I2C_WR; + msgs[0].buf = ® + msgs[0].len = 1; + + msgs[1].addr = this->i2c_addr; + msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START; + msgs[1].buf = (rt_uint8_t *)&value; + msgs[1].len = 1; + + if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) + return RT_EOK; + + return -RT_ERROR; +} + + +BMI055_Accelerometer::BMI055_Accelerometer(const char* iic_name, int addr) + : BMI055(SENSOR_TYPE_ACCELEROMETER, iic_name, addr) +{ + int index; + uint8_t id; + rt_uint8_t value[6] = {0}; + rt_int32_t x, y, z; + SensorConfig config = {SENSOR_MODE_NORMAL, SENSOR_DATARATE_400HZ, SENSOR_ACCEL_RANGE_2G}; + + write_reg(BMI055_BGW_SOFTRESET, 0xB6); /* reset of the sensor P57 */ + write_reg(BMI055_PMU_LPW, 0x00); /* PMU_LPW NORMAL mode P55 */ + write_reg(BMI055_PMU_BW, 0x0A); /* 01010b 31.25 Hz P55 */ + write_reg(BMI055_PMU_RANGE, 0x05); /* 0101b ±4g range PMU_RANGE set acc +-4g/s P54 */ + + + x_offset = y_offset = z_offset = 0; + x = y = z = 0; + + /* read BMI055 id */ + read_buffer(BMI055_ACC_BGW_CHIPID, &id, 1); /* BGW_CHIPID P47*/ + if (id != BMI055_ACC_BGW_CHIPID_VALUE) + { + printf("Warning: not found BMI055 id: %02x\n", id); + } + + /* get offset */ + for (index = 0; index < 200; index ++) + { + read_buffer(BMI055_ACCD_X_LSB, value, 6); /*ACCD_X_LSB P47 */ + + x += (((rt_int16_t)value[1] << 8) | value[0]); + y += (((rt_int16_t)value[3] << 8) | value[2]); + z += (((rt_int16_t)value[5] << 8) | value[4]); + } + x_offset = x / 200; + y_offset = y / 200; + z_offset = z / 200; + + this->enable = RT_FALSE; + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; + this->config = config; +} + +int +BMI055_Accelerometer::configure(SensorConfig *config) +{ + int range; + uint8_t value; + + if (config == RT_NULL) return -1; + + /* TODO: set datarate */ + + /* get range and calc the sensitivity */ + range = config->range.accel_range; + switch (range) + { + case SENSOR_ACCEL_RANGE_2G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; + range = 0x03; //0011b + break; + case SENSOR_ACCEL_RANGE_4G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_4G; + range = 0x05; //0101b + break; + case SENSOR_ACCEL_RANGE_8G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_8G; + range = 0x01 << 3; //1000b + break; + case SENSOR_ACCEL_RANGE_16G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_16G; + range = 0x03 << 2; //1100b + break; + default: + return -1; + } + + /* set range to sensor */ + read_reg(BMI055_PMU_RANGE, &value); /* PMU_RANGE P54 */ + value &= 0xF0; + value |= range; + write_reg(BMI055_PMU_RANGE, value); + + return 0; +} + +int +BMI055_Accelerometer::activate(int enable) +{ + uint8_t value; + + if (enable && this->enable == RT_FALSE) + { + /* enable accelerometer */ + read_reg(BMI055_PMU_LPW, &value); /* P55 */ + value &= ~(0x07 << 7); + write_reg(BMI055_PMU_LPW, value); + } + + if (!enable && this->enable == RT_TRUE) + { + /* disable accelerometer */ + read_reg(BMI055_PMU_LPW, &value); + value &= ~(0x07 << 7); + value |= (0x01 << 7); + write_reg(BMI055_PMU_LPW, value); + } + + if (enable) this->enable = RT_TRUE; + else this->enable = RT_FALSE; + + return 0; +} + +int +BMI055_Accelerometer::poll(sensors_event_t *event) +{ + rt_uint8_t value[6]; + rt_int16_t x, y, z; + + /* parameters check */ + if (event == NULL) return -1; + + /* get event data */ + event->version = sizeof(sensors_event_t); + event->sensor = (int32_t) this; + event->timestamp = rt_tick_get(); + event->type = SENSOR_TYPE_ACCELEROMETER; + + read_buffer(0x02, value, 6); + + /* get raw data */ + x = (((rt_int16_t)value[1] << 8) | value[0]); + y = (((rt_int16_t)value[3] << 8) | value[2]); + z = (((rt_int16_t)value[5] << 8) | value[4]); + + if (config.mode == SENSOR_MODE_RAW) + { + event->raw_acceleration.x = x; + event->raw_acceleration.y = y; + event->raw_acceleration.z = z; + } + else + { + + x -= x_offset; y -= y_offset; z -= z_offset; + event->acceleration.x = x * this->sensitivity * SENSORS_GRAVITY_STANDARD; + event->acceleration.y = y * this->sensitivity * SENSORS_GRAVITY_STANDARD; + event->acceleration.z = z * this->sensitivity * SENSORS_GRAVITY_STANDARD; + } + + return 0; +} + +void +BMI055_Accelerometer::getSensor(sensor_t *sensor) +{ + /* get sensor description */ + if (sensor) + { + memcpy(sensor, &_BMI055_sensor[0], sizeof(sensor_t)); + } +} + +BMI055_Gyroscope::BMI055_Gyroscope(const char* iic_name, int addr) + : BMI055(SENSOR_TYPE_GYROSCOPE, iic_name, addr) +{ + int index; + uint8_t id; + rt_uint8_t value[6]; + rt_int32_t x, y, z; + + /* initialize BMI055 */ + write_reg(BMI055_MODE_LPM1_ADDR, 0x00); /* normal mode */ + write_reg(BMI055_MODE_LPM2_ADDR, 0x80); /* fast powerup */ + write_reg(BMI055_BW_ADDR, 0x03); /* ODR:400Hz Filter Bandwidth:47Hz */ + write_reg(BMI055_RANGE_ADDR, 0x00); /* 2000dps */ + + + x_offset = y_offset = z_offset = 0; + x = y = z = 0; + + /* read BMI055 id */ + read_buffer(BMI055_CHIP_ID_ADDR, &id, 1); + if (id != BMI055_GRRO_CHIP_ID) + { + printf("Warning: not found BMI055 id: %02x\n", id); + } + + /* get offset */ + for (index = 0; index < 200; index ++) + { + read_buffer(BMI055_RATE_X_LSB_ADDR, value, 6); + + x += (((rt_int16_t)value[1] << 8) | value[0]); + y += (((rt_int16_t)value[3] << 8) | value[2]); + z += (((rt_int16_t)value[5] << 8) | value[4]); + } + x_offset = x / 200; + y_offset = y / 200; + z_offset = z / 200; + + this->enable = RT_FALSE; + this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; +} + +int +BMI055_Gyroscope::configure(SensorConfig *config) +{ + int range; + uint8_t value; + + if (config == RT_NULL) return -1; + + /* TODO: set datarate */ + + /* get range and calc the sensitivity */ + range = config->range.gyro_range; + switch (range) + { + //to do add more range e.g 125DPS + //case + case SENSOR_GYRO_RANGE_250DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; + range = 0x11; + break; + case SENSOR_GYRO_RANGE_500DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_500DPS; + range = 0x10; + break; + case SENSOR_GYRO_RANGE_1000DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_1000DPS; + range = 0x01; + break; + case SENSOR_GYRO_RANGE_2000DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_2000DPS; + range = 0x00; + break; + default: + return -1; + } + + /* set range to sensor */ + read_reg(BMI055_RANGE_ADDR, &value); + value &= ~0x07; + value |= range; + write_reg(BMI055_RANGE_ADDR, value); + + return 0; +} + +int +BMI055_Gyroscope::activate(int enable) +{ + uint8_t value; + + if (enable && this->enable == RT_FALSE) + { + /* enable gyroscope */ + read_reg(BMI055_MODE_LPM1_ADDR, &value); + value &= ~(0x1010 << 4); //{0; 0} NORMAL mode + write_reg(BMI055_MODE_LPM1_ADDR, value); //P101 NORMAL mode + } + + if (!enable && this->enable == RT_TRUE) + { + /* disable gyroscope */ + read_reg(BMI055_MODE_LPM1_ADDR, &value); + value &= ~(0x01 << 5); //set bit5 deep_suspend 0 + value |= (0x01 << 7); //set bit1 suspend 1 + write_reg(BMI055_MODE_LPM1_ADDR, value); //{1; 0} SUSPEND mode + } + + if (enable) this->enable = RT_TRUE; + else this->enable = RT_FALSE; + + return 0; +} + +int +BMI055_Gyroscope::poll(sensors_event_t *event) +{ + rt_uint8_t value[6]; + rt_int16_t x, y, z; + + /* parameters check */ + if (event == NULL) return -1; + + /* get event data */ + event->version = sizeof(sensors_event_t); + event->sensor = (int32_t) this; + event->timestamp = rt_tick_get(); + event->type = SENSOR_TYPE_GYROSCOPE; + + read_buffer(BMI055_RATE_X_LSB_ADDR, value, 6); + + /* get raw data */ + x = (((rt_int16_t)value[1] << 8) | value[0]); + y = (((rt_int16_t)value[3] << 8) | value[2]); + z = (((rt_int16_t)value[5] << 8) | value[4]); + + + if (config.mode == SENSOR_MODE_RAW) + { + event->raw_gyro.x = x; + event->raw_gyro.y = y; + event->raw_gyro.z = z; + } + else + { + x -= x_offset; y -= y_offset; z -= z_offset; + event->gyro.x = x * this->sensitivity * SENSORS_DPS_TO_RADS; + event->gyro.y = y * this->sensitivity * SENSORS_DPS_TO_RADS; + event->gyro.z = z * this->sensitivity * SENSORS_DPS_TO_RADS; + } + + return 0; +} + +void +BMI055_Gyroscope::getSensor(sensor_t *sensor) +{ + /* get sensor description */ + if (sensor) + { + memcpy(sensor, &_BMI055_sensor[1], sizeof(sensor_t)); + } +} diff --git a/components/drivers/sensors/bmi055_sensor.h b/components/drivers/sensors/bmi055_sensor.h new file mode 100644 index 0000000000..7ec6d9e5cf --- /dev/null +++ b/components/drivers/sensors/bmi055_sensor.h @@ -0,0 +1,338 @@ +/* + * File : bmi055_sensor.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2014, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2015-1-11 RT_learning the first version + */ +#ifndef __BMI055_H__ +#define __BMI055_H__ + +#include <sensor.h> + +/**************************************************************************************************/ +/************************************Register map accelerometer************************************/ + +#define BMI055_ACC_I2C_ADDR1 0x18 //SDO is low(GND) +#define BMI055_ACC_I2C_ADDR2 0x19 //SDO is high(VCC) + +#define BMI055_ACC_DEFAULT_ADDRESS BMI055_ACC_I2C_ADDR2 //in the LPC54102 SPM-S + +#define BMI055_ACC_BGW_CHIPID_VALUE 0xFA + +#define BMI055_ACC_BGW_CHIPID 0x00 +/**<Address of ACC Chip ID Register */ +#define BMI055_ACCD_X_LSB 0x02 +/**< Address of X axis ACC LSB Register */ +#define BMI055_ACCD_X_MSB 0x03 +/**< Address of X axis ACC MSB Register */ +#define BMI055_ACCD_Y_LSB 0x04 +/**< Address of Y axis ACC LSB Register */ +#define BMI055_ACCD_Y_MSB 0x05 +/**< Address of Y axis ACC MSB Register */ +#define BMI055_ACCD_Z_LSB 0x06 +/**< Address of Z axis ACC LSB Register */ +#define BMI055_ACCD_Z_MSB 0x07 +/**< Address of Z axis ACC MSB Register */ +#define BMI055_ACCD_TEMP 0x08 +/**< Address of Temperature Data Register */ + +/* Status Register */ +#define BMI055_INT_STATUS_0 0x09 +/**< Address of Interrupt status Register 0 */ +#define BMI055_INT_STATUS_1 0x0A +/**< Address of Interrupt status Register 1 */ +#define BMI055_INT_STATUS_2 0x0B +/**< Address of Interrupt status Register 2 */ +#define BMI055_INT_STATUS_3 0x0C +/**< Address of Interrupt status Register 3 */ +#define BMI055_FIFO_STATUS 0x0E +/**< Address of FIFO status Register */ + +/* Control Register */ +#define BMI055_PMU_RANGE 0x0F +/**< Address of Range address Register */ +#define BMI055_PMU_BW 0x10 +/**< Address of Bandwidth Register */ +#define BMI055_PMU_LPW 0x11 +/**< Address of PMU LPW */ +#define BMI055_PMU_LOW_POWER 0x12 +/**< Address of PMU LOW POWER */ +#define BMI055_ACCD_HBW 0x13 +/**< Address of ACCD HBW */ +#define BMI055_BGW_SOFTRESET 0x14 +/**< Address of BGW SOFTRESET */ +#define BMI055_INT_EN_0 0x16 +/**< Address of interrupt engines in group 0 */ +#define BMI055_INT_EN_1 0x17 +/**< Address of interrupt engines in group 1 */ +#define BMI055_INT_EN_2 0x18 +/**< Address of interrupt engines in group 2 */ +#define BMI055_INT_MAP_0 0x19 +/**< Address of Interrupt MAP 0 */ +#define BMI055_INT_MAP_1 0x1A +/**< Address of Interrupt MAP 1 */ +#define BMI055_INT_MAP_2 0x1B +/**< Address of Interrupt MAP 2 */ +#define BMI055_INT_SRC 0x1E +/**< Address of Interrupt source */ +#define BMI055_INT_OUT_CTRL 0x20 +/**< Address of Interrupt Register */ +#define BMI055_INT_RST_LATCH 0x21 +/**< Address of Interrupt reset and mode Register */ +#define BMI055_INT_0 0x22 +/**< Address of low-g Interrupt delay time Register */ +#define BMI055_INT_1 0x23 +/**< Address of low-g Interrupt threshold Register */ +#define BMI055_INT_2 0x24 +/**< Address of Interrupt 2 Register */ +#define BMI055_INT_3 0x25 +/**< Address of high-g Interrupt delay time Register */ +#define BMI055_INT_4 0x26 +/**< Address of high-g Interrupt threshold Register */ +#define BMI055_INT_5 0x27 +/**< Address of high-g Interrupt 5 Register */ +#define BMI055_INT_6 0x28 +/**< Address of any-motion Interrupt threshold Register */ +#define BMI055_INT_7 0x29 +/**< Address of slow/no-motion interrupt threshold Register */ +#define BMI055_INT_8 0x2A +/**< Address of high-g Interrupt 8 Register */ +#define BMI055_INT_9 0x2B +/**< Address of high-g Interrupt 9 Register */ +#define BMI055_INT_A 0x2C +/**< Address of Interrupt A Register */ +#define BMI055_INT_B 0x2D +/**< Address of Interrupt B Register */ +#define BMI055_INT_C 0x2E +/**< Address of Interrupt C Register */ +#define BMI055_INT_D 0x2F +/**< Address of Interrupt D Register */ +#define BMI055_FIFO_CONFIG_0 0x30 +/**< Address of FIFO CONFIG 0 Register */ +#define BMI055_PMU_SELF_TEST 0x32 +/**< Address of PMU SELF TEST Register */ +#define BMI055_TRIM_NVM_CTRL 0x33 +/**< Address of TRIM NVM CTRL Register */ +#define BMI055_BGW_SPI3_WDT 0x34 +/**< Address of BGW SPI3 WDT Register */ +#define BMI055_OFC_CTRL 0x36 +/**< Address of OFC CTRL Register */ +#define BMI055_OFC_SETTING 0x37 +/**< Address of OFC SETTING Register */ +#define BMI055_OFC_OFFSET_X 0x38 +/**< Address of OFC OFFSET X Register */ +#define BMI055_OFC_OFFSET_Y 0x39 +/**< Address of OFC OFFSET Y Register */ +#define BMI055_OFC_OFFSET_Z 0x3A +/**< Address of OFC OFFSET Z Register */ + +/* Trim Register */ +#define BMI055_TRIM_GP0 0x3B +/**< Address of TRIM GP0 Register */ +#define BMI055_TRIM_GP1 0x3C +/**< Address of TRIM GP1 Register */ + +/* Control Register */ +#define BMI055_FIFO_CONFIG_1 0x3E +/**< Address of FIFO CONFIG 1 Register */ + +/* Data Register */ +#define BMI055_FIFO_DATA 0x3F +/**< Address of FIFO DATA Register */ + + +/**************************************************************************************************/ + + + + +/**************************************************************************************************/ +/************************************Register map gyroscope****************************************/ + + +/**< This refers BMI055 return type as signed */ + +// #define BMI055_I2C_ADDR1 0x68 //SDO is low(GND) +// #define BMI055_I2C_ADDR2 0x69 //SDO is high(VCC) +#define BMI055_GYRO_I2C_ADDR1 0x68 //SDO is low(GND) +#define BMI055_GYRO_I2C_ADDR2 0x69 //SDO is high(VCC) + +#define BMI055_GYRO_DEFAULT_ADDRESS BMI055_GYRO_I2C_ADDR2 + +#define BMI055_GRRO_CHIP_ID 0x0F + +/*Define of registers*/ + +/* Hard Wired */ +#define BMI055_CHIP_ID_ADDR 0x00 +/**<Address of Chip ID Register*/ + +/* Data Register */ +#define BMI055_RATE_X_LSB_ADDR 0x02 +/**< Address of X axis Rate LSB Register */ +#define BMI055_RATE_X_MSB_ADDR 0x03 +/**< Address of X axis Rate MSB Register */ +#define BMI055_RATE_Y_LSB_ADDR 0x04 +/**< Address of Y axis Rate LSB Register */ +#define BMI055_RATE_Y_MSB_ADDR 0x05 +/**< Address of Y axis Rate MSB Register */ +#define BMI055_RATE_Z_LSB_ADDR 0x06 +/**< Address of Z axis Rate LSB Register */ +#define BMI055_RATE_Z_MSB_ADDR 0x07 +/**< Address of Z axis Rate MSB Register */ +#define BMI055_TEMP_ADDR 0x08 +/**< Address of Temperature Data LSB Register */ + +/* Status Register */ +#define BMI055_INTR_STAT0_ADDR 0x09 +/**< Address of Interrupt status Register 0 */ +#define BMI055_INTR_STAT1_ADDR 0x0A +/**< Address of Interrupt status Register 1 */ +#define BMI055_INTR_STAT2_ADDR 0x0B +/**< Address of Interrupt status Register 2 */ +#define BMI055_INTR_STAT3_ADDR 0x0C +/**< Address of Interrupt status Register 3 */ +#define BMI055_FIFO_STAT_ADDR 0x0E +/**< Address of FIFO status Register */ + +/* Control Register */ +#define BMI055_RANGE_ADDR 0x0F +/**< Address of Range address Register */ +#define BMI055_BW_ADDR 0x10 +/**< Address of Bandwidth Register */ +#define BMI055_MODE_LPM1_ADDR 0x11 +/**< Address of Mode LPM1 Register */ +#define BMI055_MODE_LPM2_ADDR 0x12 +/**< Address of Mode LPM2 Register */ +#define BMI055_HIGH_BW_ADDR 0x13 +/**< Address of Rate HIGH_BW Register */ +#define BMI055_BGW_SOFT_RST_ADDR 0x14 +/**< Address of BGW Softreset Register */ +#define BMI055_INTR_ENABLE0_ADDR 0x15 +/**< Address of Interrupt Enable 0 */ +#define BMI055_INTR_ENABLE1_ADDR 0x16 +/**< Address of Interrupt Enable 1 */ +#define BMI055_INTR_MAP_ZERO_ADDR 0x17 +/**< Address of Interrupt MAP 0 */ +#define BMI055_INTR_MAP_ONE_ADDR 0x18 +/**< Address of Interrupt MAP 1 */ +#define BMI055_INTR_MAP_TWO_ADDR 0x19 +/**< Address of Interrupt MAP 2 */ +#define BMI055_INTR_ZERO_ADDR 0x1A +/**< Address of Interrupt 0 register */ +#define BMI055_INTR_ONE_ADDR 0x1B +/**< Address of Interrupt 1 register */ +#define BMI055_INTR_TWO_ADDR 0x1C +/**< Address of Interrupt 2 register */ +#define BMI055_INTR_4_ADDR 0x1E +/**< Address of Interrupt 4 register */ +#define BMI055_RST_LATCH_ADDR 0x21 +/**< Address of Reset Latch Register */ +#define BMI055_HIGHRATE_THRES_X_ADDR 0x22 +/**< Address of High Th x Address register */ +#define BMI055_HIGHRATE_DURN_X_ADDR 0x23 +/**< Address of High Dur x Address register */ +#define BMI055_HIGHRATE_THRES_Y_ADDR 0x24 +/**< Address of High Th y Address register */ +#define BMI055_HIGHRATE_DURN_Y_ADDR 0x25 +/**< Address of High Dur y Address register */ +#define BMI055_HIGHRATE_THRES_Z_ADDR 0x26 +/**< Address of High Th z Address register */ +#define BMI055_HIGHRATE_DURN_Z_ADDR 0x27 +/**< Address of High Dur z Address register */ +#define BMI055_SOC_ADDR 0x31 +/**< Address of SOC register */ +#define BMI055_A_FOC_ADDR 0x32 +/**< Address of A_FOC Register */ +#define BMI055_TRIM_NVM_CTRL_ADDR 0x33 +/**< Address of Trim NVM control register */ +#define BMI055_BGW_SPI3_WDT_ADDR 0x34 +/**< Address of BGW SPI3,WDT Register */ + +/* Trim Register */ +#define BMI055_OFC1_ADDR 0x36 +/**< Address of OFC1 Register */ +#define BMI055_OFC2_ADDR 0x37 +/**< Address of OFC2 Register */ +#define BMI055_OFC3_ADDR 0x38 +/**< Address of OFC3 Register */ +#define BMI055_OFC4_ADDR 0x39 +/**< Address of OFC4 Register */ +#define BMI055_TRIM_GP0_ADDR 0x3A +/**< Address of Trim GP0 Register */ +#define BMI055_TRIM_GP1_ADDR 0x3B +/**< Address of Trim GP1 Register */ +#define BMI055_SELECTF_TEST_ADDR 0x3C +/**< Address of BGW Self test Register */ + +/* Control Register */ +#define BMI055_FIFO_CGF1_ADDR 0x3D +/**< Address of FIFO CGF0 Register */ +#define BMI055_FIFO_CGF0_ADDR 0x3E +/**< Address of FIFO CGF1 Register */ + +/* Data Register */ +#define BMI055_FIFO_DATA_ADDR 0x3F +/**< Address of FIFO Data Register */ + + +/**************************************************************************************************/ + +class BMI055 :public SensorBase +{ +public: + BMI055(int sensor_type, const char* iic_bus, int addr); + + int read_reg(rt_uint8_t reg, rt_uint8_t* value); + int write_reg(rt_uint8_t reg, rt_uint8_t value); + int read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size); + +private: + struct rt_i2c_bus_device *i2c_bus; + int i2c_addr; +}; + +class BMI055_Accelerometer:public BMI055 +{ +public: + BMI055_Accelerometer(const char* iic_name, int addr); + + virtual int configure(SensorConfig *config); + virtual int activate(int enable); + + virtual int poll(sensors_event_t *event); + virtual void getSensor(sensor_t *sensor); + +private: + rt_int16_t x_offset, y_offset, z_offset; + + rt_bool_t enable; + float sensitivity; +}; + +class BMI055_Gyroscope:public BMI055 +{ +public: + BMI055_Gyroscope(const char* iic_name, int addr); + + virtual int configure(SensorConfig *config); + virtual int activate(int enable); + + virtual int poll(sensors_event_t *event); + virtual void getSensor(sensor_t *sensor); + +private: + rt_int16_t x_offset, y_offset, z_offset; + + rt_bool_t enable; + float sensitivity; +}; + +#endif diff --git a/components/drivers/sensors/mpu6050_sensor.cpp b/components/drivers/sensors/mpu6050_sensor.cpp new file mode 100644 index 0000000000..8f6557a7ce --- /dev/null +++ b/components/drivers/sensors/mpu6050_sensor.cpp @@ -0,0 +1,462 @@ +/* + * File : MPU6050_sensor.cpp + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2014, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2014-12-20 Bernard the first version + * 2015-1-11 RT_learning modify the mpu6050 initialize + */ + +#include <string.h> +#include <stdio.h> +#include <rtdevice.h> + +#include "mpu6050_sensor.h" + + +const static sensor_t _MPU6050_sensor[] = +{ + { + .name = "Accelerometer", + .vendor = "Invensense", + .version = sizeof(sensor_t), + .handle = 0, + .type = SENSOR_TYPE_ACCELEROMETER, + .maxRange = SENSOR_ACCEL_RANGE_16G, + .resolution = 1.0f, + .power = 0.5f, + .minDelay = 10000, + .fifoReservedEventCount = 0, + .fifoMaxEventCount = 64, + }, + { + .name = "Gyroscope", + .vendor = "Invensense", + .version = sizeof(sensor_t), + .handle = 0, + .type = SENSOR_TYPE_GYROSCOPE, + .maxRange = SENSOR_GYRO_RANGE_2000DPS, + .resolution = 1.0f, + .power = 0.5f, + .minDelay = 10000, + .fifoReservedEventCount = 0, + .fifoMaxEventCount = 64, + } +}; + +MPU6050::MPU6050(int sensor_type, const char* iic_bus, int addr) + : SensorBase(sensor_type) +{ + this->i2c_bus = (struct rt_i2c_bus_device *)rt_device_find(iic_bus); + if (this->i2c_bus == NULL) + { + printf("MPU6050: No IIC device:%s\n", iic_bus); + return; + } + + this->i2c_addr = addr; + + /* register to sensor manager */ + SensorManager::registerSensor(this); +} + +int MPU6050::read_reg(rt_uint8_t reg, rt_uint8_t *value) +{ + struct rt_i2c_msg msgs[2]; + + msgs[0].addr = this->i2c_addr; + msgs[0].flags = RT_I2C_WR; + msgs[0].buf = ® + msgs[0].len = 1; + + msgs[1].addr = this->i2c_addr; + msgs[1].flags = RT_I2C_RD; /* Read from slave */ + msgs[1].buf = (rt_uint8_t *)value; + msgs[1].len = 1; + + if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) + return RT_EOK; + + return -RT_ERROR; +} + +int MPU6050::read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size) +{ + struct rt_i2c_msg msgs[2]; + + msgs[0].addr = this->i2c_addr; + msgs[0].flags = RT_I2C_WR; + msgs[0].buf = ® + msgs[0].len = 1; + + msgs[1].addr = this->i2c_addr; + msgs[1].flags = RT_I2C_RD; /* Read from slave */ + msgs[1].buf = (rt_uint8_t *)value; + msgs[1].len = size; + + if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) + return RT_EOK; + + return -RT_ERROR; +} + +int MPU6050::write_reg(rt_uint8_t reg, rt_uint8_t value) +{ + struct rt_i2c_msg msgs[2]; + + msgs[0].addr = this->i2c_addr; + msgs[0].flags = RT_I2C_WR; + msgs[0].buf = ® + msgs[0].len = 1; + + msgs[1].addr = this->i2c_addr; + msgs[1].flags = RT_I2C_WR | RT_I2C_NO_START; + msgs[1].buf = (rt_uint8_t *)&value; + msgs[1].len = 1; + + if (rt_i2c_transfer(this->i2c_bus, msgs, 2) == 2) + return RT_EOK; + + return -RT_ERROR; +} + + +MPU6050_Accelerometer::MPU6050_Accelerometer(const char* iic_name, int addr) + : MPU6050(SENSOR_TYPE_ACCELEROMETER, iic_name, addr) +{ + int index; + uint8_t id; + rt_uint8_t value[6] = {0}; + rt_int32_t x, y, z; + SensorConfig config = {SENSOR_MODE_NORMAL, SENSOR_DATARATE_400HZ, SENSOR_ACCEL_RANGE_2G}; + + /* initialize MPU6050 */ + write_reg(MPU6050_PWR_MGMT_1, 0x80); /* reset mpu6050 device */ + write_reg(MPU6050_SMPLRT_DIV, 0x00); /* Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) */ + write_reg(MPU6050_PWR_MGMT_1, 0x03); /* Wake up device , set device clock Z axis gyroscope */ + write_reg(MPU6050_CONFIG, 0x03); /* set DLPF_CFG 42Hz */ + write_reg(MPU6050_GYRO_CONFIG, 0x18); /* set gyro 2000deg/s */ + write_reg(MPU6050_ACCEL_CONFIG, 0x08); /* set acc +-4g/s */ + + + x_offset = y_offset = z_offset = 0; + x = y = z = 0; + + /* read MPU6050 id */ + read_buffer(MPU6050_WHOAMI, &id, 1); + if (id != MPU6050_ID) + { + printf("Warning: not found MPU6050 id: %02x\n", id); + } + + /* get offset */ + for (index = 0; index < 200; index ++) + { + read_buffer(MPU6050_ACCEL_XOUT_H, value, 6); + + x += (((rt_int16_t)value[0] << 8) | value[1]); + y += (((rt_int16_t)value[2] << 8) | value[3]); + z += (((rt_int16_t)value[4] << 8) | value[5]); + } + x_offset = x / 200; + y_offset = y / 200; + z_offset = z / 200; + + this->enable = RT_FALSE; + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; + this->config = config; +} + +int +MPU6050_Accelerometer::configure(SensorConfig *config) +{ + int range; + uint8_t value; + + if (config == RT_NULL) return -1; + + /* TODO: set datarate */ + + /* get range and calc the sensitivity */ + range = config->range.accel_range; + switch (range) + { + case SENSOR_ACCEL_RANGE_2G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_2G; + range = 0; + break; + case SENSOR_ACCEL_RANGE_4G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_4G; + range = 0x01 << 2; + break; + case SENSOR_ACCEL_RANGE_8G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_8G; + range = 0x02 << 2; + break; + case SENSOR_ACCEL_RANGE_16G: + this->sensitivity = SENSOR_ACCEL_SENSITIVITY_16G; + range = 0x03 << 2; + break; + default: + return -1; + } + + /* set range to sensor */ + read_reg(MPU6050_ACCEL_CONFIG, &value); + value &= ~(0x3 << 2); + value |= range; + write_reg(MPU6050_ACCEL_CONFIG, value); + + return 0; +} + +int +MPU6050_Accelerometer::activate(int enable) +{ + uint8_t value; + + if (enable && this->enable == RT_FALSE) + { + /* enable accelerometer */ + read_reg(MPU6050_PWR_MGMT_2, &value); + value &= ~(0x07 << 2); + write_reg(MPU6050_PWR_MGMT_2, value); + } + + if (!enable && this->enable == RT_TRUE) + { + /* disable accelerometer */ + read_reg(MPU6050_PWR_MGMT_2, &value); + value |= (0x07 << 2); + write_reg(MPU6050_PWR_MGMT_2, value); + } + + if (enable) this->enable = RT_TRUE; + else this->enable = RT_FALSE; + + return 0; +} + +int +MPU6050_Accelerometer::poll(sensors_event_t *event) +{ + rt_uint8_t value[6]; + rt_int16_t x, y, z; + + /* parameters check */ + if (event == NULL) return -1; + + /* get event data */ + event->version = sizeof(sensors_event_t); + event->sensor = (int32_t) this; + event->timestamp = rt_tick_get(); + event->type = SENSOR_TYPE_ACCELEROMETER; + + read_buffer(MPU6050_ACCEL_XOUT_H, value, 6); + + /* get raw data */ + x = (((rt_int16_t)value[0] << 8) | value[1]); + y = (((rt_int16_t)value[2] << 8) | value[3]); + z = (((rt_int16_t)value[4] << 8) | value[5]); + + if (config.mode == SENSOR_MODE_RAW) + { + event->raw_acceleration.x = x; + event->raw_acceleration.y = y; + event->raw_acceleration.z = z; + } + else + { + + x -= x_offset; y -= y_offset; z -= z_offset; + event->acceleration.x = x * this->sensitivity * SENSORS_GRAVITY_STANDARD; + event->acceleration.y = y * this->sensitivity * SENSORS_GRAVITY_STANDARD; + event->acceleration.z = z * this->sensitivity * SENSORS_GRAVITY_STANDARD; + } + + return 0; +} + +void +MPU6050_Accelerometer::getSensor(sensor_t *sensor) +{ + /* get sensor description */ + if (sensor) + { + memcpy(sensor, &_MPU6050_sensor[0], sizeof(sensor_t)); + } +} + +MPU6050_Gyroscope::MPU6050_Gyroscope(const char* iic_name, int addr) + : MPU6050(SENSOR_TYPE_GYROSCOPE, iic_name, addr) +{ + int index; + uint8_t id; + rt_uint8_t value[6]; + rt_int32_t x, y, z; + + /* initialize MPU6050 */ + write_reg(MPU6050_PWR_MGMT_1, 0x80); /* reset mpu6050 device */ + write_reg(MPU6050_SMPLRT_DIV, 0x00); /* Sample Rate = Gyroscope Output Rate / (1 + SMPLRT_DIV) */ + write_reg(MPU6050_PWR_MGMT_1, 0x03); /* Wake up device , set device clock Z axis gyroscope */ + write_reg(MPU6050_CONFIG, 0x03); /* set DLPF_CFG 42Hz */ + write_reg(MPU6050_GYRO_CONFIG, 0x18); /* set gyro 2000deg/s */ + write_reg(MPU6050_ACCEL_CONFIG, 0x08); /* set acc +-4g/s */ + + x_offset = y_offset = z_offset = 0; + x = y = z = 0; + + /* read MPU6050 id */ + read_reg(MPU6050_WHOAMI, &id); + if (id != MPU6050_ID) + { + printf("Warning: not found MPU6050 id: %02x\n", id); + } + + /* get offset */ + for (index = 0; index < 200; index ++) + { + read_buffer(MPU6050_GYRO_XOUT_H, value, 6); + + x += (((rt_int16_t)value[0] << 8) | value[1]); + y += (((rt_int16_t)value[2] << 8) | value[3]); + z += (((rt_int16_t)value[4] << 8) | value[5]); + } + x_offset = x / 200; + y_offset = y / 200; + z_offset = z / 200; + + this->enable = RT_FALSE; + this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; +} + +int +MPU6050_Gyroscope::configure(SensorConfig *config) +{ + int range; + uint8_t value; + + if (config == RT_NULL) return -1; + + /* TODO: set datarate */ + + /* get range and calc the sensitivity */ + range = config->range.gyro_range; + switch (range) + { + case SENSOR_GYRO_RANGE_250DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_250DPS; + range = 0; + break; + case SENSOR_GYRO_RANGE_500DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_500DPS; + range = 0x01 << 2; + break; + case SENSOR_GYRO_RANGE_1000DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_1000DPS; + range = 0x02 << 2; + break; + case SENSOR_GYRO_RANGE_2000DPS: + this->sensitivity = SENSOR_GYRO_SENSITIVITY_2000DPS; + range = 0x03 << 2; + break; + default: + return -1; + } + + /* set range to sensor */ + read_reg(MPU6050_GYRO_CONFIG, &value); + value &= ~(0x3 << 2); + value |= range; + write_reg(MPU6050_GYRO_CONFIG, value); + + return 0; +} + +int +MPU6050_Gyroscope::activate(int enable) +{ + uint8_t value; + + if (enable && this->enable == RT_FALSE) + { + /* enable gyroscope */ + read_reg(MPU6050_PWR_MGMT_1, &value); + value &= ~(0x01 << 4); + write_reg(MPU6050_PWR_MGMT_1, value); + + read_reg(MPU6050_PWR_MGMT_2, &value); + value &= ~(0x07 << 0); + write_reg(MPU6050_PWR_MGMT_2, value); + } + + if (!enable && this->enable == RT_TRUE) + { + /* disable gyroscope */ + read_reg(MPU6050_PWR_MGMT_2, &value); + value |= (0x07 << 0); + write_reg(MPU6050_PWR_MGMT_2, value); + } + + if (enable) this->enable = RT_TRUE; + else this->enable = RT_FALSE; + + return 0; +} + +int +MPU6050_Gyroscope::poll(sensors_event_t *event) +{ + rt_uint8_t value[6]; + rt_int16_t x, y, z; + + /* parameters check */ + if (event == NULL) return -1; + + /* get event data */ + event->version = sizeof(sensors_event_t); + event->sensor = (int32_t) this; + event->timestamp = rt_tick_get(); + event->type = SENSOR_TYPE_GYROSCOPE; + + read_buffer(MPU6050_GYRO_XOUT_H, value, 6); + + /* get raw data */ + x = (((rt_int16_t)value[0] << 8) | value[1]); + y = (((rt_int16_t)value[2] << 8) | value[3]); + z = (((rt_int16_t)value[4] << 8) | value[5]); + + + if (config.mode == SENSOR_MODE_RAW) + { + event->raw_gyro.x = x; + event->raw_gyro.y = y; + event->raw_gyro.z = z; + } + else + { + x -= x_offset; y -= y_offset; z -= z_offset; + event->gyro.x = x * this->sensitivity * SENSORS_DPS_TO_RADS; + event->gyro.y = y * this->sensitivity * SENSORS_DPS_TO_RADS; + event->gyro.z = z * this->sensitivity * SENSORS_DPS_TO_RADS; + } + + return 0; +} + +void +MPU6050_Gyroscope::getSensor(sensor_t *sensor) +{ + /* get sensor description */ + if (sensor) + { + memcpy(sensor, &_MPU6050_sensor[1], sizeof(sensor_t)); + } +} + diff --git a/components/drivers/sensors/mpu6050_sensor.h b/components/drivers/sensors/mpu6050_sensor.h new file mode 100644 index 0000000000..c7e28ba28e --- /dev/null +++ b/components/drivers/sensors/mpu6050_sensor.h @@ -0,0 +1,193 @@ +/* + * File : MPU6050_sensor.h + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2014, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2014-12-20 Bernard the first version + * 2015-1-11 RT_learning modify the mpu6050 ID + */ + +#ifndef MPU6050_SENSOR_H__ +#define MPU6050_SENSOR_H__ + +#include <sensor.h> + +#define MPU6050_ADDRESS_AD0_LOW 0x68 // address pin low (GND), default for InvenSense evaluation board +#define MPU6050_ADDRESS_AD0_HIGH 0x69 // address pin high (VCC) +#define MPU6050_DEFAULT_ADDRESS MPU6050_ADDRESS_AD0_LOW + +#define MPU6050_XG_OFFS_TC 0x00 +#define MPU6050_YG_OFFS_TC 0x01 +#define MPU6050_ZG_OFFS_TC 0x02 +#define MPU6050_X_FINE_GAIN 0x03 +#define MPU6050_Y_FINE_GAIN 0x04 +#define MPU6050_Z_FINE_GAIN 0x05 +#define MPU6050_XA_OFFS_H 0x06 +#define MPU6050_XA_OFFS_L 0x07 +#define MPU6050_YA_OFFS_H 0x08 +#define MPU6050_YA_OFFS_L 0x09 +#define MPU6050_ZA_OFFS_H 0x0A +#define MPU6050_ZA_OFFS_L 0x0B +#define MPU6050_PRODUCT_ID 0x0C +#define MPU6050_SELF_TEST_X 0x0D +#define MPU6050_SELF_TEST_Y 0x0E +#define MPU6050_SELF_TEST_Z 0x0F +#define MPU6050_SELF_TEST_A 0x10 +#define MPU6050_XG_OFFS_USRH 0x13 +#define MPU6050_XG_OFFS_USRL 0x14 +#define MPU6050_YG_OFFS_USRH 0x15 +#define MPU6050_YG_OFFS_USRL 0x16 +#define MPU6050_ZG_OFFS_USRH 0x17 +#define MPU6050_ZG_OFFS_USRL 0x18 +#define MPU6050_SMPLRT_DIV 0x19 +#define MPU6050_CONFIG 0x1A +#define MPU6050_GYRO_CONFIG 0x1B +#define MPU6050_ACCEL_CONFIG 0x1C +#define MPU6050_ACCEL_CONFIG_2 0x1D +#define MPU6050_LP_ACCEL_ODR 0x1E +#define MPU6050_MOT_THR 0x1F +#define MPU6050_FIFO_EN 0x23 +#define MPU6050_I2C_MST_CTRL 0x24 +#define MPU6050_I2C_SLV0_ADDR 0x25 +#define MPU6050_I2C_SLV0_REG 0x26 +#define MPU6050_I2C_SLV0_CTRL 0x27 +#define MPU6050_I2C_SLV1_ADDR 0x28 +#define MPU6050_I2C_SLV1_REG 0x29 +#define MPU6050_I2C_SLV1_CTRL 0x2A +#define MPU6050_I2C_SLV2_ADDR 0x2B +#define MPU6050_I2C_SLV2_REG 0x2C +#define MPU6050_I2C_SLV2_CTRL 0x2D +#define MPU6050_I2C_SLV3_ADDR 0x2E +#define MPU6050_I2C_SLV3_REG 0x2F +#define MPU6050_I2C_SLV3_CTRL 0x30 +#define MPU6050_I2C_SLV4_ADDR 0x31 +#define MPU6050_I2C_SLV4_REG 0x32 +#define MPU6050_I2C_SLV4_DO 0x33 +#define MPU6050_I2C_SLV4_CTRL 0x34 +#define MPU6050_I2C_SLV4_DI 0x35 +#define MPU6050_I2C_MST_STATUS 0x36 +#define MPU6050_INT_PIN_CFG 0x37 +#define MPU6050_INT_ENABLE 0x38 +#define MPU6050_ACCEL_XOUT_H 0x3B +#define MPU6050_ACCEL_XOUT_L 0x3C +#define MPU6050_ACCEL_YOUT_H 0x3D +#define MPU6050_ACCEL_YOUT_L 0x3E +#define MPU6050_ACCEL_ZOUT_H 0x3F +#define MPU6050_ACCEL_ZOUT_L 0x40 +#define MPU6050_TEMP_OUT_H 0x41 +#define MPU6050_TEMP_OUT_L 0x42 +#define MPU6050_GYRO_XOUT_H 0x43 +#define MPU6050_GYRO_XOUT_L 0x44 +#define MPU6050_GYRO_YOUT_H 0x45 +#define MPU6050_GYRO_YOUT_L 0x46 +#define MPU6050_GYRO_ZOUT_H 0x47 +#define MPU6050_GYRO_ZOUT_L 0x48 +#define MPU6050_EXT_SENS_DATA_00 0x49 +#define MPU6050_EXT_SENS_DATA_01 0x4A +#define MPU6050_EXT_SENS_DATA_02 0x4B +#define MPU6050_EXT_SENS_DATA_03 0x4C +#define MPU6050_EXT_SENS_DATA_04 0x4D +#define MPU6050_EXT_SENS_DATA_05 0x4E +#define MPU6050_EXT_SENS_DATA_06 0x4F +#define MPU6050_EXT_SENS_DATA_07 0x50 +#define MPU6050_EXT_SENS_DATA_08 0x51 +#define MPU6050_EXT_SENS_DATA_09 0x52 +#define MPU6050_EXT_SENS_DATA_10 0x53 +#define MPU6050_EXT_SENS_DATA_11 0x54 +#define MPU6050_EXT_SENS_DATA_12 0x55 +#define MPU6050_EXT_SENS_DATA_13 0x56 +#define MPU6050_EXT_SENS_DATA_14 0x57 +#define MPU6050_EXT_SENS_DATA_15 0x58 +#define MPU6050_EXT_SENS_DATA_16 0x59 +#define MPU6050_EXT_SENS_DATA_17 0x5A +#define MPU6050_EXT_SENS_DATA_18 0x5B +#define MPU6050_EXT_SENS_DATA_19 0x5C +#define MPU6050_EXT_SENS_DATA_20 0x5D +#define MPU6050_EXT_SENS_DATA_21 0x5E +#define MPU6050_EXT_SENS_DATA_22 0x5F +#define MPU6050_EXT_SENS_DATA_23 0x60 +#define MPU6050_I2C_SLV0_DO 0x63 +#define MPU6050_I2C_SLV1_DO 0x64 +#define MPU6050_I2C_SLV2_DO 0x65 +#define MPU6050_I2C_SLV3_DO 0x66 +#define MPU6050_I2C_MST_DELAY_CTRL 0x67 +#define MPU6050_SIGNAL_PATH_RESET 0x68 +#define MPU6050_MOT_DETECT_CTRL 0x69 +#define MPU6050_USER_CTRL 0x6A +#define MPU6050_PWR_MGMT_1 0x6B +#define MPU6050_PWR_MGMT_2 0x6C +#define MPU6050_BANK_SEL 0x6D +#define MPU6050_MEM_START_ADDR 0x6E +#define MPU6050_MEM_R_W 0x6F +#define MPU6050_DMP_CFG_1 0x70 +#define MPU6050_DMP_CFG_2 0x71 +#define MPU6050_FIFO_COUNTH 0x72 +#define MPU6050_FIFO_COUNTL 0x73 +#define MPU6050_FIFO_R_W 0x74 +#define MPU6050_WHOAMI 0x75 +#define MPU6050_XA_OFFSET_H 0x77 +#define MPU6050_XA_OFFSET_L 0x78 +#define MPU6050_YA_OFFSET_H 0x7A +#define MPU6050_YA_OFFSET_L 0x7B +#define MPU6050_ZA_OFFSET_H 0x7D +#define MPU6050_ZA_OFFSET_L 0x7E + +#define MPU6050_ID 0x68 + +class MPU6050 :public SensorBase +{ +public: + MPU6050(int sensor_type, const char* iic_bus, int addr); + + int read_reg(rt_uint8_t reg, rt_uint8_t* value); + int write_reg(rt_uint8_t reg, rt_uint8_t value); + int read_buffer(rt_uint8_t reg, rt_uint8_t* value, rt_size_t size); + +private: + struct rt_i2c_bus_device *i2c_bus; + int i2c_addr; +}; + +class MPU6050_Accelerometer:public MPU6050 +{ +public: + MPU6050_Accelerometer(const char* iic_name, int addr); + + virtual int configure(SensorConfig *config); + virtual int activate(int enable); + + virtual int poll(sensors_event_t *event); + virtual void getSensor(sensor_t *sensor); + +private: + rt_int16_t x_offset, y_offset, z_offset; + + rt_bool_t enable; + float sensitivity; +}; + +class MPU6050_Gyroscope:public MPU6050 +{ +public: + MPU6050_Gyroscope(const char* iic_name, int addr); + + virtual int configure(SensorConfig *config); + virtual int activate(int enable); + + virtual int poll(sensors_event_t *event); + virtual void getSensor(sensor_t *sensor); + +private: + rt_int16_t x_offset, y_offset, z_offset; + + rt_bool_t enable; + float sensitivity; +}; + +#endif diff --git a/components/drivers/sensors/sensor.cpp b/components/drivers/sensors/sensor.cpp index 52718183f3..18eb8eee18 100644 --- a/components/drivers/sensors/sensor.cpp +++ b/components/drivers/sensors/sensor.cpp @@ -1,25 +1,64 @@ +/* + * File : sensors.cpp + * This file is part of RT-Thread RTOS + * COPYRIGHT (C) 2014, RT-Thread Development Team + * + * The license and distribution terms for this file may be + * found in the file LICENSE in this distribution or at + * http://www.rt-thread.org/license/LICENSE + * + * Change Logs: + * Date Author Notes + * 2014-08-03 Bernard the first version + */ + #include <stddef.h> +#include <string.h> + #include "sensor.h" /** - * Sensor + * SensorBase */ -Sensor::Sensor() +SensorBase::SensorBase(int type) { + memset(&(this->config), 0x0, sizeof(SensorConfig)); + + this->type = type; this->next = this->prev = NULL; - Subscribe(NULL, NULL); + subscribe(NULL, NULL); } -Sensor::~Sensor() +SensorBase::~SensorBase() { } -int Sensor::GetType(void) +int SensorBase::getType(void) { return this->type; } -int Sensor::Subscribe(SensorEventHandler_t *handler, void *user_data) +int SensorBase::setConfig(SensorConfig *config) +{ + int result; + + /* configure to the low level sensor */ + result = this->configure(config); + if (result == 0) + { + this->config = *config; + } + + return result; +} + +int SensorBase::getConfig(SensorConfig *config) +{ + *config = this->config; + return 0; +} + +int SensorBase::subscribe(SensorEventHandler_t *handler, void *user_data) { this->evtHandler = handler; this->userData = user_data; @@ -27,12 +66,12 @@ int Sensor::Subscribe(SensorEventHandler_t *handler, void *user_data) return 0; } -int Sensor::Publish(sensors_event_t *event) +int SensorBase::publish(sensors_event_t *event) { if (this->evtHandler != NULL) { /* invoke subscribed handler */ - (*evtHandler)(this, event, this->userData); + (*evtHandler)(event, this->userData); } return 0; @@ -41,57 +80,52 @@ int Sensor::Publish(sensors_event_t *event) /** * Sensor Manager */ -/* sensor manager instance */ -static SensorManager _sensor_manager; +/* sensors list */ +static SensorBase *sensor_list = NULL; SensorManager::SensorManager() { - sensorList = NULL; } SensorManager::~SensorManager() { } -int SensorManager::RegisterSensor(Sensor *sensor) +int SensorManager::registerSensor(SensorBase *sensor) { - SensorManager *self = &_sensor_manager; - RT_ASSERT(sensor != RT_NULL); /* add sensor into the list */ - if (self->sensorList = NULL) + if (sensor_list == NULL) { sensor->prev = sensor->next = sensor; } else { - sensor->prev = self->sensorList; - sensor->next = self->sensorList->next; + sensor_list->prev->next = sensor; + sensor->prev = sensor_list->prev; - self->sensorList->next->prev = sensor; - self->sensorList->next = sensor; + sensor_list->prev = sensor; + sensor->next = sensor_list; } /* point the sensorList to this sensor */ - self->sensorList = sensor; + sensor_list = sensor; return 0; } -int SensorManager::DeregisterSensor(Sensor *sensor) +int SensorManager::unregisterSensor(SensorBase *sensor) { - SensorManager *self = &_sensor_manager; - /* disconnect sensor list */ sensor->next->prev = sensor->prev; sensor->prev->next = sensor->next; /* check the sensorList */ - if (sensor == self->sensorList) + if (sensor == sensor_list) { - if (sensor->next == sensor) self->sensorList = NULL; /* empty list */ - else self->sensorList = sensor->next; + if (sensor->next == sensor) sensor_list = NULL; /* empty list */ + else sensor_list = sensor->next; } /* re-initialize sensor node */ @@ -100,36 +134,99 @@ int SensorManager::DeregisterSensor(Sensor *sensor) return 0; } -Sensor *SensorManager::GetDefaultSensor(int type) +SensorBase *SensorManager::getDefaultSensor(int type) { - SensorManager *self = &_sensor_manager; - Sensor *sensor = self->sensorList; + SensorBase *sensor = sensor_list; if (sensor == NULL) return NULL; do { /* find the same type */ - if (sensor->GetType() == type) return sensor; + if (sensor->getType() == type) return sensor; sensor = sensor->next; - } - while (sensor != self->sensorList); + }while (sensor != sensor_list); return NULL; } -int SensorManager::Subscribe(int type, SensorEventHandler_t *handler, void *user_data) +int SensorManager::subscribe(int type, SensorEventHandler_t *handler, void *user_data) { - Sensor *sensor; + SensorBase *sensor; - sensor = SensorManager::GetDefaultSensor(type); + sensor = SensorManager::getDefaultSensor(type); if (sensor != NULL) { - sensor->Subscribe(handler, user_data); + sensor->subscribe(handler, user_data); return 0; } return -1; } +int SensorManager::sensorEventReady(SensorBase *sensor) +{ + return 0; +} + +int SensorManager::pollSensor(SensorBase *sensor, sensors_event_t *events, int number, int duration) +{ + rt_tick_t tick; + int result, index; + + if (sensor == NULL) return -1; + + tick = rt_tick_get(); + for (index = 0; index < number; index ++) + { + result = sensor->poll(&events[index]); + if (result < 0) break; + + if (rt_tick_get() - tick > duration) break; + } + + return index; +} + +rt_sensor_t rt_sensor_get_default(int type) +{ + return (rt_sensor_t)SensorManager::getDefaultSensor(type); +} + +int rt_sensor_subscribe(rt_sensor_t sensor, SensorEventHandler_t *handler, void *user_data) +{ + SensorBase *sensor_base; + if (sensor == NULL) return -1; + + sensor_base = (SensorBase*)sensor; + + return sensor_base->subscribe(handler, user_data); +} + +int rt_sensor_poll(rt_sensor_t sensor, sensors_event_t *event) +{ + SensorBase *sensor_base; + if (sensor == NULL || event == NULL) return -1; + + sensor_base = (SensorBase*)sensor; + return sensor_base->poll(event); +} + +int rt_sensor_configure(rt_sensor_t sensor, SensorConfig *config) +{ + SensorBase *sensor_base; + if (sensor == NULL || config == NULL) return -1; + + sensor_base = (SensorBase*)sensor; + return sensor_base->setConfig(config); +} + +int rt_sensor_activate(rt_sensor_t sensor, int enable) +{ + SensorBase *sensor_base; + if (sensor == NULL) return -1; + + sensor_base = (SensorBase*)sensor; + return sensor_base->activate(enable); +} diff --git a/components/drivers/sensors/sensor.h b/components/drivers/sensors/sensor.h index 09929d1b58..2962b21a80 100644 --- a/components/drivers/sensors/sensor.h +++ b/components/drivers/sensors/sensor.h @@ -34,10 +34,11 @@ #define SENSORS_H__ #include <rtdevice.h> - #include <stdint.h> -#include <sys/cdefs.h> -#include <sys/types.h> + +#ifdef __CC_ARM /* skip warning in armcc */ +#pragma anon_unions +#endif /** * Handles must be higher than SENSORS_HANDLE_BASE and must be unique. @@ -729,14 +730,24 @@ enum * Values returned by the accelerometer in various locations in the universe. * all values are in SI units (m/s^2) */ -#define GRAVITY_SUN (275.0f) -#define GRAVITY_EARTH (9.80665f) +#define SENSORS_GRAVITY_SUN (275.0f) +#define SENSORS_GRAVITY_MOON (1.6f) +#define SENSORS_GRAVITY_EARTH (9.80665f) +#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH) /** Maximum magnetic field on Earth's surface */ -#define MAGNETIC_FIELD_EARTH_MAX (60.0f) +#define MAGNETIC_FIELD_EARTH_MAX (60.0f) /** Minimum magnetic field on Earth's surface */ -#define MAGNETIC_FIELD_EARTH_MIN (30.0f) +#define MAGNETIC_FIELD_EARTH_MIN (30.0f) + +/** Average sea level pressure is 1013.25 hPa */ +#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) + +/** Degrees/s to rad/s multiplier */ +#define SENSORS_DPS_TO_RADS (0.017453293F) +/** Gauss to micro-Tesla multiplier */ +#define SENSORS_GAUSS_TO_MICROTESLA (100) /** * status of orientation sensor @@ -772,6 +783,22 @@ typedef struct } sensors_vec_t; /** + * sensor raw vector data + */ +typedef struct +{ + struct + { + int16_t x; + int16_t y; + int16_t z; + }; + + int8_t status; + uint8_t reserved[1]; +} sensors_raw_vec_t; + +/** * uncalibrated gyroscope and magnetometer event data */ typedef struct @@ -833,15 +860,21 @@ typedef struct sensors_event_t /* acceleration values are in meter per second per second (m/s^2) */ sensors_vec_t acceleration; + /* raw acceleration data */ + sensors_raw_vec_t raw_acceleration; /* magnetic vector values are in micro-Tesla (uT) */ sensors_vec_t magnetic; + /* raw magnetic data */ + sensors_raw_vec_t raw_magnetic; /* orientation values are in degrees */ sensors_vec_t orientation; /* gyroscope values are in rad/s */ sensors_vec_t gyro; + /* raw gyroscope data */ + sensors_raw_vec_t raw_gyro; /* temperature is in degrees centigrade (Celsius) */ float temperature; @@ -887,7 +920,6 @@ typedef sensors_event_t sensors_meta_data_event_t; typedef struct sensor_t { - /* Name of this sensor. * All sensors of the same "type" must have a different "name". */ @@ -946,41 +978,111 @@ typedef struct sensor_t void *reserved[6]; } sensor_t; -class SensorConfigure +enum SensorMode +{ + SENSOR_MODE_RAW, + SENSOR_MODE_CALIBRATED, + SENSOR_MODE_NORMAL, +}; + +enum SensorAccelRange { - int32_t delay; + SENSOR_ACCEL_RANGE_2G, + SENSOR_ACCEL_RANGE_4G, + SENSOR_ACCEL_RANGE_8G, + SENSOR_ACCEL_RANGE_16G, }; +#define SENSOR_ACCEL_SENSITIVITY_2G (0.001F) +#define SENSOR_ACCEL_SENSITIVITY_4G (0.002F) +#define SENSOR_ACCEL_SENSITIVITY_8G (0.004F) +#define SENSOR_ACCEL_SENSITIVITY_16G (0.012F) -class Sensor; +enum SensorGyroRange +{ + SENSOR_GYRO_RANGE_250DPS, + SENSOR_GYRO_RANGE_500DPS, + SENSOR_GYRO_RANGE_1000DPS, + SENSOR_GYRO_RANGE_2000DPS, +}; +#define SENSOR_GYRO_SENSITIVITY_250DPS (0.00875F) +#define SENSOR_GYRO_SENSITIVITY_500DPS (0.0175F) +#define SENSOR_GYRO_SENSITIVITY_1000DPS (0.035F) +#define SENSOR_GYRO_SENSITIVITY_2000DPS (0.070F) + +enum SensorDataRate +{ + SENSOR_DATARATE_3200HZ, + SENSOR_DATARATE_1600HZ, + SENSOR_DATARATE_800HZ, + SENSOR_DATARATE_400HZ, + SENSOR_DATARATE_200HZ, + SENSOR_DATARATE_100HZ, + SENSOR_DATARATE_50HZ, + SENSOR_DATARATE_25HZ, + SENSOR_DATARATE_12_5HZ, + SENSOR_DATARATE_6_25HZ, + SENSOR_DATARATE_3_13HZ, + SENSOR_DATARATE_1_56HZ, + SENSOR_DATARATE_0_78HZ, + SENSOR_DATARATE_0_39HZ, + SENSOR_DATARATE_0_20HZ, + SENSOR_DATARATE_0_10HZ, +}; + +/** + * Sensor Configuration + */ +typedef struct SensorConfig +{ + int mode; + + enum SensorDataRate data_rate; + + union range + { + enum SensorAccelRange accel_range; + enum SensorGyroRange gyro_range; + } range; +}SensorConfig; + +typedef void (*SensorEventHandler_t)(sensors_event_t *event, void *user_data); + +#ifdef __cplusplus +class SensorBase; class SensorManager; -typedef void (*SensorEventHandler_t)(Sensor *sensor, sensors_event_t *event, void *user_data); /** * Sensor Base Class */ -class Sensor +class SensorBase { private: int type; public: - Sensor(); - ~Sensor(); + SensorBase(int type); + ~SensorBase(); - virtual int Configure(SensorConfigure *config) = 0; - virtual int Activate(int enable) = 0; + virtual int configure(SensorConfig *config) = 0; + virtual int activate(int enable) = 0; - virtual int Poll(sensors_event_t *events, int number, int duration) = 0; - virtual void GetSensor(struct sensor_t *sensor) = 0; + virtual int poll(sensors_event_t *events) = 0; + virtual void getSensor(struct sensor_t *sensor) = 0; - int GetType(void); + int getType(void); - int Subscribe(SensorEventHandler_t *handler, void *user_data); - int Publish(sensors_event_t *event); + int setConfig(SensorConfig *config); + int getConfig(SensorConfig *config); + + int subscribe(SensorEventHandler_t *handler, void *user_data); + int publish(sensors_event_t *event); protected: - Sensor *next; - Sensor *prev; + SensorBase *next; + SensorBase *prev; + + /* sensor configuration */ + SensorConfig config; SensorEventHandler_t *evtHandler; void *userData; @@ -997,15 +1099,34 @@ public: SensorManager(); ~SensorManager(); - static int RegisterSensor(Sensor *sensor); - static int DeregisterSensor(Sensor *sensor); + static int registerSensor(SensorBase *sensor); + static int unregisterSensor(SensorBase *sensor); - static Sensor *GetDefaultSensor(int type); - static int Subscribe(int type, SensorEventHandler_t *handler, void *user_data); + static SensorBase *getDefaultSensor(int type); + static int subscribe(int type, SensorEventHandler_t *handler, void *user_data); -private: - Sensor *sensorList; + static int sensorEventReady(SensorBase *sensor); + static int pollSensor(SensorBase *sensor, sensors_event_t *events, int number, int duration); }; +#endif + +/* C programming language APIs */ +/* rt_sensor_t is a C typedef for SensorBase */ +typedef void* rt_sensor_t; +#ifdef __cplusplus +extern "C" { #endif +rt_sensor_t rt_sensor_get_default(int type); + +int rt_sensor_subscribe(rt_sensor_t sensor, SensorEventHandler_t *handler, void *user_data); +int rt_sensor_activate (rt_sensor_t sensor, int enable); +int rt_sensor_configure(rt_sensor_t sensor, SensorConfig *config); +int rt_sensor_poll(rt_sensor_t sensor, sensors_event_t *event); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/drivers/serial/serial.c b/components/drivers/serial/serial.c index f04b1df4f4..bcdd4db519 100644 --- a/components/drivers/serial/serial.c +++ b/components/drivers/serial/serial.c @@ -26,6 +26,7 @@ * 2013-02-20 bernard use RT_SERIAL_RB_BUFSZ to define * the size of ring buffer. * 2014-07-10 bernard rewrite serial framework + * 2014-12-31 bernard use open_flag for poll_tx stream mode. */ #include <rthw.h> @@ -67,7 +68,7 @@ rt_inline int _serial_poll_tx(struct rt_serial_device *serial, const rt_uint8_t * to be polite with serial console add a line feed * to the carriage return character */ - if (*data == '\n' && (serial->parent.flag & RT_DEVICE_FLAG_STREAM)) + if (*data == '\n' && (serial->parent.open_flag & RT_DEVICE_FLAG_STREAM)) { serial->ops->putc(serial, '\r'); } diff --git a/components/drivers/src/ringbuffer.c b/components/drivers/src/ringbuffer.c index 6212b10258..8c2705ceb1 100644 --- a/components/drivers/src/ringbuffer.c +++ b/components/drivers/src/ringbuffer.c @@ -100,13 +100,13 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, const rt_uint8_t *ptr, rt_uint16_t length) { - enum rt_ringbuffer_state old_state; + rt_uint16_t space_length; RT_ASSERT(rb != RT_NULL); - old_state = rt_ringbuffer_status(rb); + space_length = rt_ringbuffer_space_len(rb); - if (length > rb->buffer_size) + if (length > space_length) length = rb->buffer_size; if (rb->buffer_size - rb->write_index > length) @@ -117,7 +117,7 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, * length of data in current mirror */ rb->write_index += length; - if (old_state == RT_RINGBUFFER_FULL) + if (length > space_length) rb->read_index = rb->write_index; return length; @@ -134,7 +134,7 @@ rt_size_t rt_ringbuffer_put_force(struct rt_ringbuffer *rb, rb->write_mirror = ~rb->write_mirror; rb->write_index = length - (rb->buffer_size - rb->write_index); - if (old_state == RT_RINGBUFFER_FULL) + if (length > space_length) { rb->read_mirror = ~rb->read_mirror; rb->read_index = rb->write_index; |
