diff options
| author | 陈豪 | Jacob Chen <[email protected]> | 2015-03-29 18:35:44 +0800 |
|---|---|---|
| committer | 陈豪 | Jacob Chen <[email protected]> | 2015-03-29 18:35:44 +0800 |
| commit | 9a4dacaad743801c9be2dbae49251c4e1b8f99a9 (patch) | |
| tree | 34def3bef5c5fc4a9b7594eba5a2729f8c86aab0 /components/drivers | |
| parent | daac5388afe5a18d51e9839719de8423b62b00c1 (diff) | |
| parent | 5af7abd8c2e8b8a39c0bf096bdf9b5cb08f266fa (diff) | |
Merge pull request #3 from RT-Thread/master
111
Diffstat (limited to 'components/drivers')
21 files changed, 3632 insertions, 255 deletions
diff --git a/components/drivers/i2c/i2c_core.c b/components/drivers/i2c/i2c_core.c index f274f70fcd..09616235d1 100644 --- a/components/drivers/i2c/i2c_core.c +++ b/components/drivers/i2c/i2c_core.c @@ -24,8 +24,6 @@ #include <rtdevice.h> -static struct rt_mutex i2c_core_lock; - rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, const char *bus_name) { @@ -33,17 +31,12 @@ rt_err_t rt_i2c_bus_device_register(struct rt_i2c_bus_device *bus, rt_mutex_init(&bus->lock, "i2c_bus_lock", RT_IPC_FLAG_FIFO); - rt_mutex_take(&i2c_core_lock, RT_WAITING_FOREVER); - - if (bus->timeout == 0) - bus->timeout = RT_TICK_PER_SECOND; + if (bus->timeout == 0) bus->timeout = RT_TICK_PER_SECOND; res = rt_i2c_bus_device_device_init(bus, bus_name); i2c_dbg("I2C bus [%s] registered\n", bus_name); - rt_mutex_release(&i2c_core_lock); - return res; } @@ -136,6 +129,6 @@ rt_size_t rt_i2c_master_recv(struct rt_i2c_bus_device *bus, int rt_i2c_core_init(void) { - return rt_mutex_init(&i2c_core_lock, "i2c_core_lock", RT_IPC_FLAG_FIFO); + return 0; } INIT_COMPONENT_EXPORT(rt_i2c_core_init); 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/drivers/serial.h b/components/drivers/include/drivers/serial.h index bf2a25ae1e..3b0a009072 100644 --- a/components/drivers/include/drivers/serial.h +++ b/components/drivers/include/drivers/serial.h @@ -65,11 +65,6 @@ #define RT_SERIAL_RB_BUFSZ 64 #endif -#define RT_DEVICE_CTRL_CONFIG 0x03 /* configure device */ -#define RT_DEVICE_CTRL_SET_INT 0x10 /* enable receive irq */ -#define RT_DEVICE_CTRL_CLR_INT 0x11 /* disable receive irq */ -#define RT_DEVICE_CTRL_GET_INT 0x12 - #define RT_SERIAL_EVENT_RX_IND 0x01 /* Rx indication */ #define RT_SERIAL_EVENT_TX_DONE 0x02 /* Tx complete */ #define RT_SERIAL_EVENT_RX_DMADONE 0x03 /* Rx DMA transfer done */ 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..f3577a11d5 --- /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, name, 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 new file mode 100644 index 0000000000..db409cfd2b --- /dev/null +++ b/components/drivers/sensors/SConscript @@ -0,0 +1,17 @@ +# SConscript for sensor framework + +from building import * + +cwd = GetCurrentDir() +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 new file mode 100644 index 0000000000..18eb8eee18 --- /dev/null +++ b/components/drivers/sensors/sensor.cpp @@ -0,0 +1,232 @@ +/* + * 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" + +/** + * SensorBase + */ +SensorBase::SensorBase(int type) +{ + memset(&(this->config), 0x0, sizeof(SensorConfig)); + + this->type = type; + this->next = this->prev = NULL; + subscribe(NULL, NULL); +} + +SensorBase::~SensorBase() +{ +} + +int SensorBase::getType(void) +{ + return this->type; +} + +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; + + return 0; +} + +int SensorBase::publish(sensors_event_t *event) +{ + if (this->evtHandler != NULL) + { + /* invoke subscribed handler */ + (*evtHandler)(event, this->userData); + } + + return 0; +} + +/** + * Sensor Manager + */ +/* sensors list */ +static SensorBase *sensor_list = NULL; + +SensorManager::SensorManager() +{ +} + +SensorManager::~SensorManager() +{ +} + +int SensorManager::registerSensor(SensorBase *sensor) +{ + RT_ASSERT(sensor != RT_NULL); + + /* add sensor into the list */ + if (sensor_list == NULL) + { + sensor->prev = sensor->next = sensor; + } + else + { + sensor_list->prev->next = sensor; + sensor->prev = sensor_list->prev; + + sensor_list->prev = sensor; + sensor->next = sensor_list; + } + + /* point the sensorList to this sensor */ + sensor_list = sensor; + + return 0; +} + +int SensorManager::unregisterSensor(SensorBase *sensor) +{ + /* disconnect sensor list */ + sensor->next->prev = sensor->prev; + sensor->prev->next = sensor->next; + + /* check the sensorList */ + if (sensor == sensor_list) + { + if (sensor->next == sensor) sensor_list = NULL; /* empty list */ + else sensor_list = sensor->next; + } + + /* re-initialize sensor node */ + sensor->next = sensor->prev = sensor; + + return 0; +} + +SensorBase *SensorManager::getDefaultSensor(int type) +{ + SensorBase *sensor = sensor_list; + + if (sensor == NULL) return NULL; + + do + { + /* find the same type */ + if (sensor->getType() == type) return sensor; + + sensor = sensor->next; + }while (sensor != sensor_list); + + return NULL; +} + +int SensorManager::subscribe(int type, SensorEventHandler_t *handler, void *user_data) +{ + SensorBase *sensor; + + sensor = SensorManager::getDefaultSensor(type); + if (sensor != NULL) + { + 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 new file mode 100644 index 0000000000..2962b21a80 --- /dev/null +++ b/components/drivers/sensors/sensor.h @@ -0,0 +1,1132 @@ +/* + * File : sensors.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-08-03 Bernard the first version + */ + +/* Modified from: https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */ + +/* + * Copyright (C) 2012 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef SENSORS_H__ +#define SENSORS_H__ + +#include <rtdevice.h> +#include <stdint.h> + +#ifdef __CC_ARM /* skip warning in armcc */ +#pragma anon_unions +#endif + +/** + * Handles must be higher than SENSORS_HANDLE_BASE and must be unique. + * A Handle identifies a given sensors. The handle is used to activate + * and/or deactivate sensors. + * In this version of the API there can only be 256 handles. + */ +#define SENSORS_HANDLE_BASE 0 +#define SENSORS_HANDLE_BITS 8 +#define SENSORS_HANDLE_COUNT (1<<SENSORS_HANDLE_BITS) + + +/* + * flags for (*batch)() + * Availability: SENSORS_DEVICE_API_VERSION_1_0 + * see (*batch)() documentation for details + */ +enum +{ + SENSORS_BATCH_DRY_RUN = 0x00000001, + SENSORS_BATCH_WAKE_UPON_FIFO_FULL = 0x00000002 +}; + +/* + * what field for meta_data_event_t + */ +enum +{ + /* a previous flush operation has completed */ + META_DATA_FLUSH_COMPLETE = 1, + META_DATA_VERSION /* always last, leave auto-assigned */ +}; + +/** + * Definition of the axis used by the sensor HAL API + * + * This API is relative to the screen of the device in its default orientation, + * that is, if the device can be used in portrait or landscape, this API + * is only relative to the NATURAL orientation of the screen. In other words, + * the axis are not swapped when the device's screen orientation changes. + * Higher level services /may/ perform this transformation. + * + * x<0 x>0 + * ^ + * | + * +-----------+--> y>0 + * | | + * | | + * | | + * | | / z<0 + * | | / + * | | / + * O-----------+/ + * |[] [ ] []/ + * +----------/+ y<0 + * / + * / + * |/ z>0 (toward the sky) + * + * O: Origin (x=0,y=0,z=0) + * + */ + +/* + * Interaction with suspend mode + * + * Unless otherwise noted, an enabled sensor shall not prevent the + * SoC to go into suspend mode. It is the responsibility of applications + * to keep a partial wake-lock should they wish to receive sensor + * events while the screen is off. While in suspend mode, and unless + * otherwise noted (batch mode, sensor particularities, ...), enabled sensors' + * events are lost. + * + * Note that conceptually, the sensor itself is not de-activated while in + * suspend mode -- it's just that the data it returns are lost. As soon as + * the SoC gets out of suspend mode, operations resume as usual. Of course, + * in practice sensors shall be disabled while in suspend mode to + * save power, unless batch mode is active, in which case they must + * continue fill their internal FIFO (see the documentation of batch() to + * learn how suspend interacts with batch mode). + * + * In batch mode, and only when the flag SENSORS_BATCH_WAKE_UPON_FIFO_FULL is + * set and supported, the specified sensor must be able to wake-up the SoC and + * be able to buffer at least 10 seconds worth of the requested sensor events. + * + * There are notable exceptions to this behavior, which are sensor-dependent + * (see sensor types definitions below) + * + * + * The sensor type documentation below specifies the wake-up behavior of + * each sensor: + * wake-up: yes this sensor must wake-up the SoC to deliver events + * wake-up: no this sensor shall not wake-up the SoC, events are dropped + * + */ + +/* + * Sensor type + * + * Each sensor has a type which defines what this sensor measures and how + * measures are reported. All types are defined below. + * + * Device manufacturers (OEMs) can define their own sensor types, for + * their private use by applications or services provided by them. Such + * sensor types are specific to an OEM and can't be exposed in the SDK. + * These types must start at SENSOR_TYPE_DEVICE_PRIVATE_BASE. + */ + +/* + * Base for device manufacturers private sensor types. + * These sensor types can't be exposed in the SDK. + */ +#define SENSOR_TYPE_DEVICE_PRIVATE_BASE 0x10000 + +/* + * Sensor fusion and virtual sensors + * + * Many sensor types are or can be implemented as virtual sensors from + * physical sensors on the device. For instance the rotation vector sensor, + * orientation sensor, step-detector, step-counter, etc... + * + * From the point of view of this API these virtual sensors MUST appear as + * real, individual sensors. It is the responsibility of the driver and HAL + * to make sure this is the case. + * + * In particular, all sensors must be able to function concurrently. + * For example, if defining both an accelerometer and a step counter, + * then both must be able to work concurrently. + */ + +/* + * Trigger modes + * + * Sensors can report events in different ways called trigger modes, + * each sensor type has one and only one trigger mode associated to it. + * Currently there are four trigger modes defined: + * + * continuous: events are reported at a constant rate defined by setDelay(). + * eg: accelerometers, gyroscopes. + * on-change: events are reported only if the sensor's value has changed. + * setDelay() is used to set a lower limit to the reporting + * period (minimum time between two events). + * The HAL must return an event immediately when an on-change + * sensor is activated. + * eg: proximity, light sensors + * one-shot: upon detection of an event, the sensor deactivates itself and + * then sends a single event. Order matters to avoid race + * conditions. No other event is sent until the sensor get + * reactivated. setDelay() is ignored. + * eg: significant motion sensor + * special: see details in the sensor type specification below + * + */ + +/* + * SENSOR_TYPE_META_DATA + * trigger-mode: n/a + * wake-up sensor: n/a + * + * NO SENSOR OF THAT TYPE MUST BE RETURNED (*get_sensors_list)() + * + * SENSOR_TYPE_META_DATA is a special token used to populate the + * sensors_meta_data_event structure. It doesn't correspond to a physical + * sensor. sensors_meta_data_event are special, they exist only inside + * the HAL and are generated spontaneously, as opposed to be related to + * a physical sensor. + * + * sensors_meta_data_event_t.version must be META_DATA_VERSION + * sensors_meta_data_event_t.sensor must be 0 + * sensors_meta_data_event_t.type must be SENSOR_TYPE_META_DATA + * sensors_meta_data_event_t.reserved must be 0 + * sensors_meta_data_event_t.timestamp must be 0 + * + * The payload is a meta_data_event_t, where: + * meta_data_event_t.what can take the following values: + * + * META_DATA_FLUSH_COMPLETE + * This event indicates that a previous (*flush)() call has completed for the sensor + * handle specified in meta_data_event_t.sensor. + * see (*flush)() for more details + * + * All other values for meta_data_event_t.what are reserved and + * must not be used. + * + */ +#define SENSOR_TYPE_META_DATA (0) + +/* + * SENSOR_TYPE_ACCELEROMETER + * trigger-mode: continuous + * wake-up sensor: no + * + * All values are in SI units (m/s^2) and measure the acceleration of the + * device minus the force of gravity. + * + * Acceleration sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * x: Acceleration on the x-axis + * y: Acceleration on the y-axis + * z: Acceleration on the z-axis + * + * Note that the readings from the accelerometer include the acceleration + * due to gravity (which is opposite to the direction of the gravity vector). + * + * Examples: + * The norm of <x, y, z> should be close to 0 when in free fall. + * + * When the device lies flat on a table and is pushed on its left side + * toward the right, the x acceleration value is positive. + * + * When the device lies flat on a table, the acceleration value is +9.81, + * which correspond to the acceleration of the device (0 m/s^2) minus the + * force of gravity (-9.81 m/s^2). + * + * When the device lies flat on a table and is pushed toward the sky, the + * acceleration value is greater than +9.81, which correspond to the + * acceleration of the device (+A m/s^2) minus the force of + * gravity (-9.81 m/s^2). + */ +#define SENSOR_TYPE_ACCELEROMETER (1) + +/* + * SENSOR_TYPE_GEOMAGNETIC_FIELD + * trigger-mode: continuous + * wake-up sensor: no + * + * All values are in micro-Tesla (uT) and measure the geomagnetic + * field in the X, Y and Z axis. + * + * Returned values include calibration mechanisms such that the vector is + * aligned with the magnetic declination and heading of the earth's + * geomagnetic field. + * + * Magnetic Field sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + */ +#define SENSOR_TYPE_GEOMAGNETIC_FIELD (2) +#define SENSOR_TYPE_MAGNETIC_FIELD SENSOR_TYPE_GEOMAGNETIC_FIELD + +/* + * SENSOR_TYPE_ORIENTATION + * trigger-mode: continuous + * wake-up sensor: no + * + * All values are angles in degrees. + * + * Orientation sensors return sensor events for all 3 axes at a constant + * rate defined by setDelay(). + * + * azimuth: angle between the magnetic north direction and the Y axis, around + * the Z axis (0<=azimuth<360). + * 0=North, 90=East, 180=South, 270=West + * + * pitch: Rotation around X axis (-180<=pitch<=180), with positive values when + * the z-axis moves toward the y-axis. + * + * roll: Rotation around Y axis (-90<=roll<=90), with positive values when + * the x-axis moves towards the z-axis. + * + * Note: For historical reasons the roll angle is positive in the clockwise + * direction (mathematically speaking, it should be positive in the + * counter-clockwise direction): + * + * Z + * ^ + * (+roll) .--> | + * / | + * | | roll: rotation around Y axis + * X <-------(.) + * Y + * note that +Y == -roll + * + * + * + * Note: This definition is different from yaw, pitch and roll used in aviation + * where the X axis is along the long side of the plane (tail to nose). + */ +#define SENSOR_TYPE_ORIENTATION (3) + +/* + * SENSOR_TYPE_GYROSCOPE + * trigger-mode: continuous + * wake-up sensor: no + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. The coordinate system is the same as is + * used for the acceleration sensor. Rotation is positive in the + * counter-clockwise direction (right-hand rule). That is, an observer + * looking from some positive location on the x, y or z axis at a device + * positioned on the origin would report positive rotation if the device + * appeared to be rotating counter clockwise. Note that this is the + * standard mathematical definition of positive rotation and does not agree + * with the definition of roll given earlier. + * The range should at least be 17.45 rad/s (ie: ~1000 deg/s). + * + * automatic gyro-drift compensation is allowed but not required. + */ +#define SENSOR_TYPE_GYROSCOPE (4) + +/* + * SENSOR_TYPE_LIGHT + * trigger-mode: on-change + * wake-up sensor: no + * + * The light sensor value is returned in SI lux units. + */ +#define SENSOR_TYPE_LIGHT (5) + +/* + * SENSOR_TYPE_PRESSURE + * trigger-mode: continuous + * wake-up sensor: no + * + * The pressure sensor return the athmospheric pressure in hectopascal (hPa) + */ +#define SENSOR_TYPE_PRESSURE (6) + +/* SENSOR_TYPE_TEMPERATURE is deprecated in the HAL */ +#define SENSOR_TYPE_TEMPERATURE (7) + +/* + * SENSOR_TYPE_PROXIMITY + * trigger-mode: on-change + * wake-up sensor: yes + * + * The distance value is measured in centimeters. Note that some proximity + * sensors only support a binary "close" or "far" measurement. In this case, + * the sensor should report its maxRange value in the "far" state and a value + * less than maxRange in the "near" state. + */ +#define SENSOR_TYPE_PROXIMITY (8) + +/* + * SENSOR_TYPE_GRAVITY + * trigger-mode: continuous + * wake-up sensor: no + * + * A gravity output indicates the direction of and magnitude of gravity in + * the devices's coordinates. On Earth, the magnitude is 9.8 m/s^2. + * Units are m/s^2. The coordinate system is the same as is used for the + * acceleration sensor. When the device is at rest, the output of the + * gravity sensor should be identical to that of the accelerometer. + */ +#define SENSOR_TYPE_GRAVITY (9) + +/* + * SENSOR_TYPE_LINEAR_ACCELERATION + * trigger-mode: continuous + * wake-up sensor: no + * + * Indicates the linear acceleration of the device in device coordinates, + * not including gravity. + * + * The output is conceptually: + * output of TYPE_ACCELERATION - output of TYPE_GRAVITY + * + * Readings on all axes should be close to 0 when device lies on a table. + * Units are m/s^2. + * The coordinate system is the same as is used for the acceleration sensor. + */ +#define SENSOR_TYPE_LINEAR_ACCELERATION (10) + +/* + * SENSOR_TYPE_ROTATION_VECTOR + * trigger-mode: continuous + * wake-up sensor: no + * + * The rotation vector symbolizes the orientation of the device relative to the + * East-North-Up coordinates frame. It is usually obtained by integration of + * accelerometer, gyroscope and magnetometer readings. + * + * The East-North-Up coordinate system is defined as a direct orthonormal basis + * where: + * - X points east and is tangential to the ground. + * - Y points north and is tangential to the ground. + * - Z points towards the sky and is perpendicular to the ground. + * + * The orientation of the phone is represented by the rotation necessary to + * align the East-North-Up coordinates with the phone's coordinates. That is, + * applying the rotation to the world frame (X,Y,Z) would align them with the + * phone coordinates (x,y,z). + * + * The rotation can be seen as rotating the phone by an angle theta around + * an axis rot_axis to go from the reference (East-North-Up aligned) device + * orientation to the current device orientation. + * + * The rotation is encoded as the 4 (reordered) components of a unit quaternion: + * sensors_event_t.data[0] = rot_axis.x*sin(theta/2) + * sensors_event_t.data[1] = rot_axis.y*sin(theta/2) + * sensors_event_t.data[2] = rot_axis.z*sin(theta/2) + * sensors_event_t.data[3] = cos(theta/2) + * where + * - rot_axis.x,y,z are the North-East-Up coordinates of a unit length vector + * representing the rotation axis + * - theta is the rotation angle + * + * The quaternion must be of norm 1 (it is a unit quaternion). Failure to ensure + * this will cause erratic client behaviour. + * + * In addition, this sensor reports an estimated heading accuracy. + * sensors_event_t.data[4] = estimated_accuracy (in radians) + * The heading error must be less than estimated_accuracy 95% of the time + * + * This sensor must use a gyroscope and an accelerometer as main orientation + * change input. + * + * This sensor can also include magnetometer input to make up for gyro drift, + * but it cannot be implemented using only a magnetometer. + */ +#define SENSOR_TYPE_ROTATION_VECTOR (11) + +/* + * SENSOR_TYPE_RELATIVE_HUMIDITY + * trigger-mode: on-change + * wake-up sensor: no + * + * A relative humidity sensor measures relative ambient air humidity and + * returns a value in percent. + */ +#define SENSOR_TYPE_RELATIVE_HUMIDITY (12) + +/* + * SENSOR_TYPE_AMBIENT_TEMPERATURE + * trigger-mode: on-change + * wake-up sensor: no + * + * The ambient (room) temperature in degree Celsius. + */ +#define SENSOR_TYPE_AMBIENT_TEMPERATURE (13) + +/* + * SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED + * trigger-mode: continuous + * wake-up sensor: no + * + * Similar to SENSOR_TYPE_MAGNETIC_FIELD, but the hard iron calibration is + * reported separately instead of being included in the measurement. + * Factory calibration and temperature compensation should still be applied to + * the "uncalibrated" measurement. + * Separating away the hard iron calibration estimation allows the system to + * better recover from bad hard iron estimation. + * + * All values are in micro-Tesla (uT) and measure the ambient magnetic + * field in the X, Y and Z axis. Assumptions that the the magnetic field + * is due to the Earth's poles should be avoided. + * + * The uncalibrated_magnetic event contains + * - 3 fields for uncalibrated measurement: x_uncalib, y_uncalib, z_uncalib. + * Each is a component of the measured magnetic field, with soft iron + * and temperature compensation applied, but not hard iron calibration. + * These values should be continuous (no re-calibration should cause a jump). + * - 3 fields for hard iron bias estimates: x_bias, y_bias, z_bias. + * Each field is a component of the estimated hard iron calibration. + * They represent the offsets to apply to the calibrated readings to obtain + * uncalibrated readings (x_uncalib ~= x_calibrated + x_bias) + * These values are expected to jump as soon as the estimate of the hard iron + * changes, and they should be stable the rest of the time. + * + * If this sensor is present, then the corresponding + * SENSOR_TYPE_MAGNETIC_FIELD must be present and both must return the + * same sensor_t::name and sensor_t::vendor. + * + * Minimum filtering should be applied to this sensor. In particular, low pass + * filters should be avoided. + * + * See SENSOR_TYPE_MAGNETIC_FIELD for more information + */ +#define SENSOR_TYPE_MAGNETIC_FIELD_UNCALIBRATED (14) + +/* + * SENSOR_TYPE_GAME_ROTATION_VECTOR + * trigger-mode: continuous + * wake-up sensor: no + * + * Similar to SENSOR_TYPE_ROTATION_VECTOR, but not using the geomagnetic + * field. Therefore the Y axis doesn't point north, but instead to some other + * reference. That reference is allowed to drift by the same order of + * magnitude than the gyroscope drift around the Z axis. + * + * This sensor does not report an estimated heading accuracy: + * sensors_event_t.data[4] is reserved and should be set to 0 + * + * In the ideal case, a phone rotated and returning to the same real-world + * orientation should report the same game rotation vector + * (without using the earth's geomagnetic field). + * + * This sensor must be based on a gyroscope. It cannot be implemented using + * a magnetometer. + * + * see SENSOR_TYPE_ROTATION_VECTOR for more details + */ +#define SENSOR_TYPE_GAME_ROTATION_VECTOR (15) + +/* + * SENSOR_TYPE_GYROSCOPE_UNCALIBRATED + * trigger-mode: continuous + * wake-up sensor: no + * + * All values are in radians/second and measure the rate of rotation + * around the X, Y and Z axis. An estimation of the drift on each axis is + * reported as well. + * + * No gyro-drift compensation shall be performed. + * Factory calibration and temperature compensation should still be applied + * to the rate of rotation (angular speeds). + * + * The coordinate system is the same as is + * used for the acceleration sensor. Rotation is positive in the + * counter-clockwise direction (right-hand rule). That is, an observer + * looking from some positive location on the x, y or z axis at a device + * positioned on the origin would report positive rotation if the device + * appeared to be rotating counter clockwise. Note that this is the + * standard mathematical definition of positive rotation and does not agree + * with the definition of roll given earlier. + * The range should at least be 17.45 rad/s (ie: ~1000 deg/s). + * + * Content of an uncalibrated_gyro event: (units are rad/sec) + * x_uncalib : angular speed (w/o drift compensation) around the X axis + * y_uncalib : angular speed (w/o drift compensation) around the Y axis + * z_uncalib : angular speed (w/o drift compensation) around the Z axis + * x_bias : estimated drift around X axis in rad/s + * y_bias : estimated drift around Y axis in rad/s + * z_bias : estimated drift around Z axis in rad/s + * + * IMPLEMENTATION NOTES: + * + * If the implementation is not able to estimate the drift, then this + * sensor MUST NOT be reported by this HAL. Instead, the regular + * SENSOR_TYPE_GYROSCOPE is used without drift compensation. + * + * If this sensor is present, then the corresponding + * SENSOR_TYPE_GYROSCOPE must be present and both must return the + * same sensor_t::name and sensor_t::vendor. + */ +#define SENSOR_TYPE_GYROSCOPE_UNCALIBRATED (16) + +/* + * SENSOR_TYPE_SIGNIFICANT_MOTION + * trigger-mode: one-shot + * wake-up sensor: yes + * + * A sensor of this type triggers an event each time significant motion + * is detected and automatically disables itself. + * The only allowed value to return is 1.0. + * + * A significant motion is a motion that might lead to a change in the user + * location. + * Examples of such motions are: + * walking, biking, sitting in a moving car, coach or train. + * Examples of situations that should not trigger significant motion: + * - phone in pocket and person is not moving + * - phone is on a table, even if the table shakes a bit due to nearby traffic + * or washing machine + * + * A note on false positive / false negative / power consumption tradeoff + * - The goal of this sensor is to save power. + * - Triggering an event when the user is not moving (false positive) is costly + * in terms of power, so it should be avoided. + * - Not triggering an event when the user is moving (false negative) is + * acceptable as long as it is not done repeatedly. If the user has been + * walking for 10 seconds, not triggering an event within those 10 seconds + * is not acceptable. + * + * IMPORTANT NOTE: this sensor type is very different from other types + * in that it must work when the screen is off without the need of + * holding a partial wake-lock and MUST allow the SoC to go into suspend. + * When significant motion is detected, the sensor must awaken the SoC and + * the event be reported. + * + * If a particular hardware cannot support this mode of operation then this + * sensor type MUST NOT be reported by the HAL. ie: it is not acceptable + * to "emulate" this sensor in the HAL. + * + * The whole point of this sensor type is to save power by keeping the + * SoC in suspend mode when the device is at rest. + * + * When the sensor is not activated, it must also be deactivated in the + * hardware: it must not wake up the SoC anymore, even in case of + * significant motion. + * + * setDelay() has no effect and is ignored. + * Once a "significant motion" event is returned, a sensor of this type + * must disables itself automatically, as if activate(..., 0) had been called. + */ + +#define SENSOR_TYPE_SIGNIFICANT_MOTION (17) + +/* + * SENSOR_TYPE_STEP_DETECTOR + * trigger-mode: special + * wake-up sensor: no + * + * A sensor of this type triggers an event each time a step is taken + * by the user. The only allowed value to return is 1.0 and an event is + * generated for each step. Like with any other event, the timestamp + * indicates when the event (here the step) occurred, this corresponds to when + * the foot hit the ground, generating a high variation in acceleration. + * + * While this sensor operates, it shall not disrupt any other sensors, in + * particular, but not limited to, the accelerometer; which might very well + * be in use as well. + * + * This sensor must be low power. That is, if the step detection cannot be + * done in hardware, this sensor should not be defined. Also, when the + * step detector is activated and the accelerometer is not, only steps should + * trigger interrupts (not accelerometer data). + * + * setDelay() has no impact on this sensor type + */ + +#define SENSOR_TYPE_STEP_DETECTOR (18) + +/* + * SENSOR_TYPE_STEP_COUNTER + * trigger-mode: on-change + * wake-up sensor: no + * + * A sensor of this type returns the number of steps taken by the user since + * the last reboot while activated. The value is returned as a uint64_t and is + * reset to zero only on a system / android reboot. + * + * The timestamp of the event is set to the time when the first step + * for that event was taken. + * See SENSOR_TYPE_STEP_DETECTOR for the signification of the time of a step. + * + * The minimum size of the hardware's internal counter shall be 16 bits + * (this restriction is here to avoid too frequent wake-ups when the + * delay is very large). + * + * IMPORTANT NOTE: this sensor type is different from other types + * in that it must work when the screen is off without the need of + * holding a partial wake-lock and MUST allow the SoC to go into suspend. + * Unlike other sensors, while in suspend mode this sensor must stay active, + * no events are reported during that time but, steps continue to be + * accounted for; an event will be reported as soon as the SoC resumes if + * the timeout has expired. + * + * In other words, when the screen is off and the device allowed to + * go into suspend mode, we don't want to be woken up, regardless of the + * setDelay() value, but the steps shall continue to be counted. + * + * The driver must however ensure that the internal step count never + * overflows. It is allowed in this situation to wake the SoC up so the + * driver can do the counter maintenance. + * + * While this sensor operates, it shall not disrupt any other sensors, in + * particular, but not limited to, the accelerometer; which might very well + * be in use as well. + * + * If a particular hardware cannot support these modes of operation then this + * sensor type MUST NOT be reported by the HAL. ie: it is not acceptable + * to "emulate" this sensor in the HAL. + * + * This sensor must be low power. That is, if the step detection cannot be + * done in hardware, this sensor should not be defined. Also, when the + * step counter is activated and the accelerometer is not, only steps should + * trigger interrupts (not accelerometer data). + * + * The whole point of this sensor type is to save power by keeping the + * SoC in suspend mode when the device is at rest. + */ + +#define SENSOR_TYPE_STEP_COUNTER (19) + +/* + * SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR + * trigger-mode: continuous + * wake-up sensor: no + * + * Similar to SENSOR_TYPE_ROTATION_VECTOR, but using a magnetometer instead + * of using a gyroscope. + * + * This sensor must be based on a magnetometer. It cannot be implemented using + * a gyroscope, and gyroscope input cannot be used by this sensor, as the + * goal of this sensor is to be low power. + * The accelerometer can be (and usually is) used. + * + * Just like SENSOR_TYPE_ROTATION_VECTOR, this sensor reports an estimated + * heading accuracy: + * sensors_event_t.data[4] = estimated_accuracy (in radians) + * The heading error must be less than estimated_accuracy 95% of the time + * + * see SENSOR_TYPE_ROTATION_VECTOR for more details + */ +#define SENSOR_TYPE_GEOMAGNETIC_ROTATION_VECTOR (20) + +/** + * Values returned by the accelerometer in various locations in the universe. + * all values are in SI units (m/s^2) + */ +#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) + +/** Minimum magnetic field on Earth's surface */ +#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 + */ +#define SENSOR_STATUS_UNRELIABLE 0 +#define SENSOR_STATUS_ACCURACY_LOW 1 +#define SENSOR_STATUS_ACCURACY_MEDIUM 2 +#define SENSOR_STATUS_ACCURACY_HIGH 3 + +/** + * sensor event data + */ +typedef struct +{ + union + { + float v[3]; + struct + { + float x; + float y; + float z; + }; + struct + { + float azimuth; + float pitch; + float roll; + }; + }; + int8_t status; + uint8_t reserved[3]; +} 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 +{ + union + { + float uncalib[3]; + struct + { + float x_uncalib; + float y_uncalib; + float z_uncalib; + }; + }; + union + { + float bias[3]; + struct + { + float x_bias; + float y_bias; + float z_bias; + }; + }; +} uncalibrated_event_t; + +typedef struct meta_data_event +{ + int32_t what; + int32_t sensor; +} meta_data_event_t; + +/** + * Union of the various types of sensor data + * that can be returned. + */ +typedef struct sensors_event_t +{ + /* must be sizeof(struct sensors_event_t) */ + int32_t version; + + /* sensor identifier */ + int32_t sensor; + + /* sensor type */ + int32_t type; + + /* reserved */ + int32_t reserved0; + + /* time is in nanosecond */ + int64_t timestamp; + + union + { + union + { + float data[16]; + + /* 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; + + /* distance in centimeters */ + float distance; + + /* light in SI lux units */ + float light; + + /* pressure in hectopascal (hPa) */ + float pressure; + + /* relative humidity in percent */ + float relative_humidity; + + /* uncalibrated gyroscope values are in rad/s */ + uncalibrated_event_t uncalibrated_gyro; + + /* uncalibrated magnetometer values are in micro-Teslas */ + uncalibrated_event_t uncalibrated_magnetic; + + /* this is a special event. see SENSOR_TYPE_META_DATA above. + * sensors_meta_data_event_t events are all reported with a type of + * SENSOR_TYPE_META_DATA. The handle is ignored and must be zero. + */ + meta_data_event_t meta_data; + }; + + union + { + uint64_t data[8]; + + /* step-counter */ + uint64_t step_counter; + } u64; + }; + uint32_t reserved1[4]; +} sensors_event_t; + +/* see SENSOR_TYPE_META_DATA */ +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". + */ + const char *name; + + /* vendor of the hardware part */ + const char *vendor; + + /* version of the hardware part + driver. The value of this field + * must increase when the driver is updated in a way that changes the + * output of this sensor. This is important for fused sensors when the + * fusion algorithm is updated. + */ + int version; + + /* handle that identifies this sensors. This handle is used to reference + * this sensor throughout the HAL API. + */ + int handle; + + /* this sensor's type. */ + int type; + + /* maximum range of this sensor's value in SI units */ + float maxRange; + + /* smallest difference between two values reported by this sensor */ + float resolution; + + /* rough estimate of this sensor's power consumption in mA */ + float power; + + /* this value depends on the trigger mode: + * + * continuous: minimum sample period allowed in microseconds + * on-change : 0 + * one-shot :-1 + * special : 0, unless otherwise noted + */ + int32_t minDelay; + + /* number of events reserved for this sensor in the batch mode FIFO. + * If there is a dedicated FIFO for this sensor, then this is the + * size of this FIFO. If the FIFO is shared with other sensors, + * this is the size reserved for that sensor and it can be zero. + */ + uint32_t fifoReservedEventCount; + + /* maximum number of events of this sensor that could be batched. + * This is especially relevant when the FIFO is shared between + * several sensors; this value is then set to the size of that FIFO. + */ + uint32_t fifoMaxEventCount; + + /* reserved fields, must be zero */ + void *reserved[6]; +} sensor_t; + +enum SensorMode +{ + SENSOR_MODE_RAW, + SENSOR_MODE_CALIBRATED, + SENSOR_MODE_NORMAL, +}; + +enum SensorAccelRange +{ + 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) + +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; + +/** + * Sensor Base Class + */ +class SensorBase +{ +private: + int type; + +public: + SensorBase(int type); + ~SensorBase(); + + virtual int configure(SensorConfig *config) = 0; + virtual int activate(int enable) = 0; + + virtual int poll(sensors_event_t *events) = 0; + virtual void getSensor(struct sensor_t *sensor) = 0; + + int getType(void); + + int setConfig(SensorConfig *config); + int getConfig(SensorConfig *config); + + int subscribe(SensorEventHandler_t *handler, void *user_data); + int publish(sensors_event_t *event); + +protected: + SensorBase *next; + SensorBase *prev; + + /* sensor configuration */ + SensorConfig config; + + SensorEventHandler_t *evtHandler; + void *userData; + + friend class SensorManager; +}; + +/** + * Sensor Manager + */ +class SensorManager +{ +public: + SensorManager(); + ~SensorManager(); + + static int registerSensor(SensorBase *sensor); + static int unregisterSensor(SensorBase *sensor); + + static SensorBase *getDefaultSensor(int type); + static int subscribe(int type, SensorEventHandler_t *handler, void *user_data); + + 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..8744aa4657 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'); } @@ -278,7 +279,7 @@ static rt_err_t rt_serial_open(struct rt_device *dev, rt_uint16_t oflag) serial->config.bufsz); RT_ASSERT(rx_fifo != RT_NULL); rx_fifo->buffer = (rt_uint8_t*) (rx_fifo + 1); - rt_memset(rx_fifo->buffer, 0, RT_SERIAL_RB_BUFSZ); + rt_memset(rx_fifo->buffer, 0, serial->config.bufsz); rx_fifo->put_index = 0; rx_fifo->get_index = 0; diff --git a/components/drivers/spi/spi_wifi_rw009.c b/components/drivers/spi/spi_wifi_rw009.c index 4906a97712..9f5601bf26 100644 --- a/components/drivers/spi/spi_wifi_rw009.c +++ b/components/drivers/spi/spi_wifi_rw009.c @@ -20,6 +20,7 @@ * Change Logs: * Date Author Notes * 2014-07-31 aozima the first version + * 2014-09-18 aozima update command & response. */ #include <rtthread.h> @@ -30,24 +31,33 @@ #include <lwip/icmp.h> #include "lwipopts.h" -#include "spi_wifi_rw009.h" - -#define SSID_NAME "AP_SSID" -#define SSID_PASSWORD "AP_passwd" - -// #define WIFI_DEBUG_ON +#define WIFI_DEBUG_ON // #define ETH_RX_DUMP // #define ETH_TX_DUMP #ifdef WIFI_DEBUG_ON -#define WIFI_DEBUG rt_kprintf("[WIFI] ");rt_kprintf +#define WIFI_DEBUG rt_kprintf("[RW009] ");rt_kprintf +//#define SPI_DEBUG rt_kprintf("[SPI] ");rt_kprintf +#define SPI_DEBUG(...) #else #define WIFI_DEBUG(...) +#define SPI_DEBUG(...) #endif /* #ifdef WIFI_DEBUG_ON */ -#define MAX_BUFFER_SIZE (sizeof(struct response) + MAX_DATA_LEN) +/********************************* RW009 **************************************/ +#include "spi_wifi_rw009.h" + +/* tools */ +#define node_entry(node, type, member) \ + ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member))) +#define member_offset(type, member) \ + ((unsigned long)(&((type *)0)->member)) + +#define MAX_SPI_PACKET_SIZE (member_offset(struct spi_data_packet, buffer) + SPI_MAX_DATA_LEN) +#define MAX_SPI_BUFFER_SIZE (sizeof(struct spi_response) + MAX_SPI_PACKET_SIZE) #define MAX_ADDR_LEN 6 -struct spi_wifi_eth + +struct rw009_wifi { /* inherit from ethernet device */ struct eth_device parent; @@ -67,8 +77,9 @@ struct spi_wifi_eth int spi_tx_mb_pool[SPI_TX_POOL_SIZE + 1]; int eth_rx_mb_pool[SPI_RX_POOL_SIZE + 1]; - int spi_wifi_cmd_mb_pool[3]; - struct rt_mailbox spi_wifi_cmd_mb; + int rw009_cmd_mb_pool[3]; + struct rt_mailbox rw009_cmd_mb; + uint32_t last_cmd; ALIGN(4) rt_uint8_t spi_tx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_TX_POOL_SIZE]; @@ -76,58 +87,257 @@ struct spi_wifi_eth rt_uint8_t spi_rx_mempool[(sizeof(struct spi_data_packet) + 4) * SPI_RX_POOL_SIZE]; ALIGN(4) - uint8_t spi_hw_rx_buffer[MAX_BUFFER_SIZE]; + uint8_t spi_hw_rx_buffer[MAX_SPI_BUFFER_SIZE]; + + /* status for RW009 */ + rw009_ap_info ap_info; /* AP info for conn. */ + rw009_ap_info *ap_scan; /* AP list for SCAN. */ + uint32_t ap_scan_count; }; -static struct spi_wifi_eth spi_wifi_device; +static struct rw009_wifi rw009_wifi_device; static struct rt_event spi_wifi_data_event; -static void resp_handler(struct spi_wifi_eth *wifi_device, struct spi_wifi_resp *resp) +static void resp_handler(struct rw009_wifi *wifi_device, struct rw009_resp *resp) { - struct spi_wifi_resp *resp_return; + struct rw009_resp *resp_return = RT_NULL; switch (resp->cmd) { - case SPI_WIFI_CMD_INIT: - WIFI_DEBUG("resp_handler SPI_WIFI_CMD_INIT\n"); - resp_return = (struct spi_wifi_resp *)rt_malloc(sizeof(struct spi_wifi_resp)); //TODO: - memcpy(resp_return, resp, 10); - rt_mb_send(&wifi_device->spi_wifi_cmd_mb, (rt_uint32_t)resp_return); + case RW009_CMD_INIT: + WIFI_DEBUG("resp_handler RW009_CMD_INIT\n"); + resp_return = (struct rw009_resp *)rt_malloc(member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_init)); //TODO: + if(resp_return == RT_NULL) break; + memcpy(resp_return, resp, member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_init)); + + WIFI_DEBUG("sn:%-*.*s\n", sizeof(resp->resp.init.sn), sizeof(resp->resp.init.sn), resp->resp.init.sn); + WIFI_DEBUG("version:%-*.*s\n", sizeof(resp->resp.init.version), sizeof(resp->resp.init.version), resp->resp.init.version); + + rt_memcpy(wifi_device->dev_addr, resp->resp.init.mac, 6); break; - case SPI_WIFI_CMD_SCAN: - WIFI_DEBUG("resp_handler SPI_WIFI_CMD_SCAN\n"); + case RW009_CMD_SCAN: + if( resp->len == sizeof(rw009_ap_info) ) + { + rw009_ap_info *ap_scan = rt_realloc(wifi_device->ap_scan, sizeof(rw009_ap_info) * (wifi_device->ap_scan_count + 1) ); + if(ap_scan != RT_NULL) + { + memcpy( &ap_scan[wifi_device->ap_scan_count], &resp->resp.ap_info, sizeof(rw009_ap_info) ); + + //dump + if(1) + { +#ifdef WIFI_DEBUG_ON + rw009_ap_info *ap_info = &resp->resp.ap_info; + WIFI_DEBUG("SCAN SSID:%-32.32s\n", ap_info->ssid); + WIFI_DEBUG("SCAN BSSID:%02X-%02X-%02X-%02X-%02X-%02X\n", + ap_info->bssid[0], + ap_info->bssid[1], + ap_info->bssid[2], + ap_info->bssid[3], + ap_info->bssid[4], + ap_info->bssid[5]); + WIFI_DEBUG("SCAN rssi:%ddBm\n", ap_info->rssi); + WIFI_DEBUG("SCAN rate:%dMbps\n", ap_info->max_data_rate/1000); + WIFI_DEBUG("SCAN channel:%d\n", ap_info->channel); + WIFI_DEBUG("SCAN security:%08X\n\n", ap_info->security); +#endif /* WIFI_DEBUG_ON */ + } + + wifi_device->ap_scan_count++; + wifi_device->ap_scan = ap_scan; + } + + return; /* wait for next ap */ + } break; + case RW009_CMD_JOIN: + case RW009_CMD_EASY_JOIN: + WIFI_DEBUG("resp_handler RW009_CMD_EASY_JOIN\n"); + resp_return = (struct rw009_resp *)rt_malloc(member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_join)); //TODO: + if(resp_return == RT_NULL) break; + memcpy(resp_return, resp, member_offset(struct rw009_resp, resp) + sizeof(rw009_resp_join)); + + if( resp->result == 0 ) + { + memcpy(&wifi_device->ap_info, &resp_return->resp.ap_info, sizeof(rw009_resp_join)); + wifi_device->active = 1; + eth_device_linkchange(&wifi_device->parent, RT_TRUE); + } + else + { + WIFI_DEBUG("RW009_CMD_EASY_JOIN result: %d\n", resp->result ); + } - case SPI_WIFI_CMD_JOIN: - WIFI_DEBUG("resp_handler SPI_WIFI_CMD_JOIN\n"); - wifi_device->active = 1; - eth_device_linkchange(&wifi_device->parent, RT_TRUE); + //dupm + if(1) + { +#ifdef WIFI_DEBUG_ON + rw009_ap_info *ap_info = &resp->resp.ap_info; + WIFI_DEBUG("JOIN SSID:%-32.32s\n", ap_info->ssid); + WIFI_DEBUG("JOIN BSSID:%02X-%02X-%02X-%02X-%02X-%02X\n", + ap_info->bssid[0], + ap_info->bssid[1], + ap_info->bssid[2], + ap_info->bssid[3], + ap_info->bssid[4], + ap_info->bssid[5]); + WIFI_DEBUG("JOIN rssi:%ddBm\n", ap_info->rssi); + WIFI_DEBUG("JOIN rate:%dMbps\n", ap_info->max_data_rate/1000); + WIFI_DEBUG("JOIN channel:%d\n", ap_info->channel); + WIFI_DEBUG("JOIN security:%08X\n\n", ap_info->security); +#endif /* WIFI_DEBUG_ON */ + } break; + case RW009_CMD_RSSI: + // TODO: client RSSI. + { + rw009_ap_info *ap_info = &resp->resp.ap_info; + wifi_device->ap_info.rssi = ap_info->rssi; + WIFI_DEBUG("current RSSI: %d\n", wifi_device->ap_info.rssi); + } + break; + + case RW009_CMD_SOFTAP: + { + if( resp->result == 0 ) + { + ; + wifi_device->active = 1; + eth_device_linkchange(&wifi_device->parent, RT_TRUE); + } + else + { + WIFI_DEBUG("RW009_CMD_EASY_JOIN result: %d\n", resp->result ); + } + + } + break; + default: WIFI_DEBUG("resp_handler %d\n", resp->cmd); break; } + + if(resp->cmd == wifi_device->last_cmd) + { + rt_mb_send(&wifi_device->rw009_cmd_mb, (rt_uint32_t)resp_return); + return; + } + else + { + rt_free(resp_return); + } +} + +static rt_err_t rw009_cmd(struct rw009_wifi *wifi_device, uint32_t cmd, void *args) +{ + rt_err_t result = RT_EOK; + rt_int32_t timeout = RW009_CMD_TIMEOUT; + + struct spi_data_packet *data_packet; + struct rw009_cmd *wifi_cmd = RT_NULL; + struct rw009_resp *resp = RT_NULL; + + wifi_device->last_cmd = cmd; + + data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER); + wifi_cmd = (struct rw009_cmd *)data_packet->buffer; + + wifi_cmd->cmd = cmd; + wifi_cmd->len = 0; + + if( cmd == RW009_CMD_INIT ) + { + wifi_cmd->len = sizeof(rw009_cmd_init); + } + else if( cmd == RW009_CMD_SCAN ) + { + wifi_cmd->len = 0; + timeout += RT_TICK_PER_SECOND*10; + + if(wifi_device->ap_scan) + { + rt_free(wifi_device->ap_scan); + wifi_device->ap_scan = RT_NULL; + wifi_device->ap_scan_count = 0; + } + } + else if( cmd == RW009_CMD_JOIN ) + { + wifi_cmd->len = sizeof(rw009_cmd_join); + } + else if( cmd == RW009_CMD_EASY_JOIN ) + { + wifi_cmd->len = sizeof(rw009_cmd_easy_join); + timeout += RT_TICK_PER_SECOND*5; + } + else if( cmd == RW009_CMD_RSSI ) + { + wifi_cmd->len = sizeof(rw009_cmd_rssi); + } + else if( cmd == RW009_CMD_SOFTAP ) + { + wifi_cmd->len = sizeof(rw009_cmd_softap); + } + else + { + WIFI_DEBUG("unkown RW009 CMD %d\n", cmd); + result = -RT_ENOSYS; + rt_mp_free(data_packet); + data_packet = RT_NULL; + } + + if(data_packet == RT_NULL) + { + goto _exit; + } + + if(wifi_cmd->len) + memcpy(&wifi_cmd->params, args, wifi_cmd->len); + + data_packet->data_type = data_type_cmd; + data_packet->data_len = member_offset(struct rw009_cmd, params) + wifi_cmd->len; + + rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet); + rt_event_send(&spi_wifi_data_event, 1); + + result = rt_mb_recv(&wifi_device->rw009_cmd_mb, + (rt_uint32_t *)&resp, + timeout); + + if ( result != RT_EOK ) + { + WIFI_DEBUG("CMD %d error, resultL %d\n", cmd, result ); + } + + if(resp != RT_NULL) + result = resp->result; + +_exit: + wifi_device->last_cmd = 0; + if(resp) rt_free(resp); + return result; } -static rt_err_t spi_wifi_transfer(struct spi_wifi_eth *dev) +static rt_err_t spi_wifi_transfer(struct rw009_wifi *dev) { struct pbuf *p = RT_NULL; - struct cmd_request cmd; - struct response resp; + struct spi_cmd_request cmd; + struct spi_response resp; rt_err_t result; const struct spi_data_packet *data_packet = RT_NULL; - struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev; + struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev; struct rt_spi_device *rt_spi_device = wifi_device->rt_spi_device; spi_wifi_int_cmd(0); while (spi_wifi_is_busy()); - WIFI_DEBUG("sequence start!\n"); + SPI_DEBUG("sequence start!\n"); - memset(&cmd, 0, sizeof(struct cmd_request)); + memset(&cmd, 0, sizeof(struct spi_cmd_request)); cmd.magic1 = CMD_MAGIC1; cmd.magic2 = CMD_MAGIC2; @@ -139,7 +349,7 @@ static rt_err_t spi_wifi_transfer(struct spi_wifi_eth *dev) if ((result == RT_EOK) && (data_packet != RT_NULL) && (data_packet->data_len > 0)) { cmd.M2S_len = data_packet->data_len + member_offset(struct spi_data_packet, buffer); - //WIFI_DEBUG("cmd.M2S_len = %d\n", cmd.M2S_len); + //SPI_DEBUG("cmd.M2S_len = %d\n", cmd.M2S_len); } rt_spi_send(rt_spi_device, &cmd, sizeof(cmd)); @@ -163,22 +373,22 @@ static rt_err_t spi_wifi_transfer(struct spi_wifi_eth *dev) if ((resp.magic1 != RESP_MAGIC1) || (resp.magic2 != RESP_MAGIC2)) { - WIFI_DEBUG("bad resp magic, abort!\n"); + SPI_DEBUG("bad resp magic, abort!\n"); goto _bad_resp_magic; } if (resp.flag & RESP_FLAG_SRDY) { - WIFI_DEBUG("RESP_FLAG_SRDY\n"); + SPI_DEBUG("RESP_FLAG_SRDY\n"); max_data_len = cmd.M2S_len; } if (resp.S2M_len) { - WIFI_DEBUG("resp.S2M_len: %d\n", resp.S2M_len); + SPI_DEBUG("resp.S2M_len: %d\n", resp.S2M_len); if (resp.S2M_len > MAX_SPI_PACKET_SIZE) { - WIFI_DEBUG("resp.S2M_len %d > %d(MAX_SPI_PACKET_SIZE), drop!\n", resp.S2M_len, MAX_SPI_PACKET_SIZE); + SPI_DEBUG("resp.S2M_len %d > %d(MAX_SPI_PACKET_SIZE), drop!\n", resp.S2M_len, MAX_SPI_PACKET_SIZE); resp.S2M_len = 0;//drop } @@ -188,10 +398,10 @@ static rt_err_t spi_wifi_transfer(struct spi_wifi_eth *dev) if (max_data_len == 0) { - WIFI_DEBUG("no rx or tx data!\n"); + SPI_DEBUG("no rx or tx data!\n"); } - //WIFI_DEBUG("max_data_len = %d\n", max_data_len); + //SPI_DEBUG("max_data_len = %d\n", max_data_len); _bad_resp_magic: /* setup message */ @@ -227,25 +437,25 @@ _bad_resp_magic: } else { - WIFI_DEBUG("!active, RX drop.\n"); + SPI_DEBUG("!active, RX drop.\n"); } } else if (data_packet->data_type == data_type_resp) { - WIFI_DEBUG("data_type_resp\n"); - resp_handler(dev, (struct spi_wifi_resp *)data_packet->buffer); + SPI_DEBUG("data_type_resp\n"); + resp_handler(dev, (struct rw009_resp *)data_packet->buffer); } else { - WIFI_DEBUG("data_type: %d, %dbyte\n", - data_packet->data_type, - data_packet->data_len); + SPI_DEBUG("data_type: %d, %dbyte\n", + data_packet->data_type, + data_packet->data_len); } } } spi_wifi_int_cmd(1); - WIFI_DEBUG("sequence finish!\n\n"); + SPI_DEBUG("sequence finish!\n\n"); if ((cmd.M2S_len == 0) && (resp.S2M_len == 0)) { @@ -289,127 +499,57 @@ static void packet_dump(const char *msg, const struct pbuf *p) } #endif /* dump */ -/* initialize the interface */ -static rt_err_t spi_wifi_eth_init(rt_device_t dev) +/********************************* RT-Thread Ethernet interface begin **************************************/ +static rt_err_t rw009_wifi_init(rt_device_t dev) { return RT_EOK; } -static rt_err_t spi_wifi_eth_open(rt_device_t dev, rt_uint16_t oflag) +static rt_err_t rw009_wifi_open(rt_device_t dev, rt_uint16_t oflag) { return RT_EOK; } -static rt_err_t spi_wifi_eth_close(rt_device_t dev) +static rt_err_t rw009_wifi_close(rt_device_t dev) { return RT_EOK; } -static rt_size_t spi_wifi_eth_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) +static rt_size_t rw009_wifi_read(rt_device_t dev, rt_off_t pos, void *buffer, rt_size_t size) { rt_set_errno(-RT_ENOSYS); return 0; } -static rt_size_t spi_wifi_eth_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) +static rt_size_t rw009_wifi_write(rt_device_t dev, rt_off_t pos, const void *buffer, rt_size_t size) { rt_set_errno(-RT_ENOSYS); return 0; } - -static rt_err_t spi_wifi_eth_control(rt_device_t dev, rt_uint8_t cmd, void *args) +static rt_err_t rw009_wifi_control(rt_device_t dev, rt_uint8_t cmd, void *args) { - struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev; - struct spi_data_packet *data_packet; - struct spi_wifi_cmd *wifi_cmd; - struct spi_wifi_resp *resp; + struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev; + rt_err_t result = RT_EOK; - switch (cmd) + if (cmd == NIOCTL_GADDR) { - case NIOCTL_GADDR: memcpy(args, wifi_device->dev_addr, 6); - break; - - case SPI_WIFI_CMD_INIT: - /* get mac address */ - if (args) - { - rt_err_t result; - - data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER); - // TODO: check result. - - wifi_cmd = (struct spi_wifi_cmd *)data_packet->buffer; - wifi_cmd->cmd = SPI_WIFI_CMD_INIT; - - data_packet->data_type = data_type_cmd; - data_packet->data_len = member_offset(struct spi_wifi_cmd, buffer) + 0; - - rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet); - rt_event_send(&spi_wifi_data_event, 1); - - result = rt_mb_recv(&wifi_device->spi_wifi_cmd_mb, - (rt_uint32_t *)&resp, - RT_WAITING_FOREVER); - - if ((result == RT_EOK) && (resp != RT_NULL)) - { - WIFI_DEBUG("resp cmd: %d\n", resp->cmd); - - rt_memcpy(args, resp->buffer, 6); - } - } - else return -RT_ERROR; - break; - - - case SPI_WIFI_CMD_SCAN: - - case SPI_WIFI_CMD_JOIN: - if (args) - { - struct cmd_join *cmd_join; - - data_packet = (struct spi_data_packet *)rt_mp_alloc(&wifi_device->spi_tx_mp, RT_WAITING_FOREVER); - - wifi_cmd = (struct spi_wifi_cmd *)data_packet->buffer; - wifi_cmd->cmd = SPI_WIFI_CMD_JOIN; - cmd_join = (struct cmd_join *)wifi_cmd->buffer; - -#define WPA_SECURITY 0x00200000 -#define WPA2_SECURITY 0x00400000 - -#define TKIP_ENABLED 0x0002 -#define AES_ENABLED 0x0004 - - - strncpy(cmd_join->ssid, SSID_NAME, SSID_NAME_LENGTH_MAX); - strncpy(cmd_join->passwd, SSID_PASSWORD, PASSWORD_LENGTH_MAX); - cmd_join->security = WPA_SECURITY | TKIP_ENABLED | AES_ENABLED; - // cmd_join->security = WPA_SECURITY | TKIP_ENABLED; - data_packet->data_type = data_type_cmd; - data_packet->data_len = sizeof(struct cmd_join) + member_offset(struct spi_wifi_cmd, buffer); - - rt_mb_send(&wifi_device->spi_tx_mb, (rt_uint32_t)data_packet); - rt_event_send(&spi_wifi_data_event, 1); - } - else return -RT_ERROR; - break; - - default : - break; + } + else + { + result = rw009_cmd(wifi_device, cmd, args); } - return RT_EOK; + return result; } /* transmit packet. */ -rt_err_t spi_wifi_eth_tx(rt_device_t dev, struct pbuf *p) +rt_err_t rw009_wifi_tx(rt_device_t dev, struct pbuf *p) { rt_err_t result = RT_EOK; struct spi_data_packet *data_packet; - struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev; + struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev; if (!wifi_device->active) { @@ -441,10 +581,10 @@ rt_err_t spi_wifi_eth_tx(rt_device_t dev, struct pbuf *p) } /* reception packet. */ -struct pbuf *spi_wifi_eth_rx(rt_device_t dev) +struct pbuf *rw009_wifi_rx(rt_device_t dev) { struct pbuf *p = RT_NULL; - struct spi_wifi_eth *wifi_device = (struct spi_wifi_eth *)dev; + struct rw009_wifi *wifi_device = (struct rw009_wifi *)dev; if (rt_mb_recv(&wifi_device->eth_rx_mb, (rt_uint32_t *)&p, 0) != RT_EOK) { @@ -452,12 +592,13 @@ struct pbuf *spi_wifi_eth_rx(rt_device_t dev) } #ifdef ETH_RX_DUMP - if(p) - packet_dump("RX dump", p); + if(p) + packet_dump("RX dump", p); #endif /* ETH_RX_DUMP */ return p; } +/********************************* RT-Thread Ethernet interface end **************************************/ static void spi_wifi_data_thread_entry(void *parameter) { @@ -476,7 +617,7 @@ static void spi_wifi_data_thread_entry(void *parameter) continue; } - result = spi_wifi_transfer(&spi_wifi_device); + result = spi_wifi_transfer(&rw009_wifi_device); if (result == RT_EOK) { @@ -485,15 +626,19 @@ static void spi_wifi_data_thread_entry(void *parameter) } } -rt_err_t rt_hw_wifi_init(const char *spi_device_name) +rt_err_t rt_hw_wifi_init(const char *spi_device_name, wifi_mode_t mode) { - memset(&spi_wifi_device, 0, sizeof(struct spi_wifi_eth)); + /* align and struct size check. */ + RT_ASSERT( (SPI_MAX_DATA_LEN & 0x03) == 0); + RT_ASSERT( sizeof(struct rw009_resp) <= SPI_MAX_DATA_LEN); - spi_wifi_device.rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); + memset(&rw009_wifi_device, 0, sizeof(struct rw009_wifi)); - if (spi_wifi_device.rt_spi_device == RT_NULL) + rw009_wifi_device.rt_spi_device = (struct rt_spi_device *)rt_device_find(spi_device_name); + + if (rw009_wifi_device.rt_spi_device == RT_NULL) { - WIFI_DEBUG("spi device %s not found!\r\n", spi_device_name); + SPI_DEBUG("spi device %s not found!\r\n", spi_device_name); return -RT_ENOSYS; } @@ -502,49 +647,49 @@ rt_err_t rt_hw_wifi_init(const char *spi_device_name) struct rt_spi_configuration cfg; cfg.data_width = 8; cfg.mode = RT_SPI_MODE_0 | RT_SPI_MSB; /* SPI Compatible: Mode 0. */ - cfg.max_hz = 15 * 1000000; /* 30M */ - rt_spi_configure(spi_wifi_device.rt_spi_device, &cfg); + cfg.max_hz = 15 * 1000000; /* 10M */ + rt_spi_configure(rw009_wifi_device.rt_spi_device, &cfg); } - spi_wifi_device.parent.parent.init = spi_wifi_eth_init; - spi_wifi_device.parent.parent.open = spi_wifi_eth_open; - spi_wifi_device.parent.parent.close = spi_wifi_eth_close; - spi_wifi_device.parent.parent.read = spi_wifi_eth_read; - spi_wifi_device.parent.parent.write = spi_wifi_eth_write; - spi_wifi_device.parent.parent.control = spi_wifi_eth_control; - spi_wifi_device.parent.parent.user_data = RT_NULL; + rw009_wifi_device.parent.parent.init = rw009_wifi_init; + rw009_wifi_device.parent.parent.open = rw009_wifi_open; + rw009_wifi_device.parent.parent.close = rw009_wifi_close; + rw009_wifi_device.parent.parent.read = rw009_wifi_read; + rw009_wifi_device.parent.parent.write = rw009_wifi_write; + rw009_wifi_device.parent.parent.control = rw009_wifi_control; + rw009_wifi_device.parent.parent.user_data = RT_NULL; - spi_wifi_device.parent.eth_rx = spi_wifi_eth_rx; - spi_wifi_device.parent.eth_tx = spi_wifi_eth_tx; + rw009_wifi_device.parent.eth_rx = rw009_wifi_rx; + rw009_wifi_device.parent.eth_tx = rw009_wifi_tx; - rt_mp_init(&spi_wifi_device.spi_tx_mp, + rt_mp_init(&rw009_wifi_device.spi_tx_mp, "spi_tx", - &spi_wifi_device.spi_tx_mempool[0], - sizeof(spi_wifi_device.spi_tx_mempool), + &rw009_wifi_device.spi_tx_mempool[0], + sizeof(rw009_wifi_device.spi_tx_mempool), sizeof(struct spi_data_packet)); - rt_mp_init(&spi_wifi_device.spi_rx_mp, + rt_mp_init(&rw009_wifi_device.spi_rx_mp, "spi_rx", - &spi_wifi_device.spi_rx_mempool[0], - sizeof(spi_wifi_device.spi_rx_mempool), + &rw009_wifi_device.spi_rx_mempool[0], + sizeof(rw009_wifi_device.spi_rx_mempool), sizeof(struct spi_data_packet)); - rt_mb_init(&spi_wifi_device.spi_tx_mb, + rt_mb_init(&rw009_wifi_device.spi_tx_mb, "spi_tx", - &spi_wifi_device.spi_tx_mb_pool[0], + &rw009_wifi_device.spi_tx_mb_pool[0], SPI_TX_POOL_SIZE, RT_IPC_FLAG_PRIO); - rt_mb_init(&spi_wifi_device.eth_rx_mb, + rt_mb_init(&rw009_wifi_device.eth_rx_mb, "eth_rx", - &spi_wifi_device.eth_rx_mb_pool[0], + &rw009_wifi_device.eth_rx_mb_pool[0], SPI_TX_POOL_SIZE, RT_IPC_FLAG_PRIO); - rt_mb_init(&spi_wifi_device.spi_wifi_cmd_mb, + rt_mb_init(&rw009_wifi_device.rw009_cmd_mb, "wifi_cmd", - &spi_wifi_device.spi_wifi_cmd_mb_pool[0], - sizeof(spi_wifi_device.spi_wifi_cmd_mb_pool) / 4, + &rw009_wifi_device.rw009_cmd_mb_pool[0], + sizeof(rw009_wifi_device.rw009_cmd_mb_pool) / 4, RT_IPC_FLAG_PRIO); rt_event_init(&spi_wifi_data_event, "wifi", RT_IPC_FLAG_FIFO); @@ -567,24 +712,18 @@ rt_err_t rt_hw_wifi_init(const char *spi_device_name) /* init: get mac address */ { - WIFI_DEBUG("wifi_control SPI_WIFI_CMD_INIT\n"); - spi_wifi_eth_control((rt_device_t)&spi_wifi_device, - SPI_WIFI_CMD_INIT, - (void *)&spi_wifi_device.dev_addr[0]); + rw009_cmd_init init; + init.mode = mode; + WIFI_DEBUG("wifi_control RW009_CMD_INIT\n"); + rw009_wifi_control((rt_device_t)&rw009_wifi_device, + RW009_CMD_INIT, + (void *)&init); // 0: firmware, 1: STA, 2:AP } - /* register eth device */ - eth_device_init(&(spi_wifi_device.parent), "w0"); - eth_device_linkchange(&spi_wifi_device.parent, RT_FALSE); - - { - WIFI_DEBUG("wifi_control SPI_WIFI_CMD_JOIN\n"); - spi_wifi_eth_control((rt_device_t)&spi_wifi_device, - SPI_WIFI_CMD_JOIN, - (void *)&spi_wifi_device.dev_addr[0]); - WIFI_DEBUG("wifi_control exit\n"); - } + /* register eth device */ + eth_device_init(&(rw009_wifi_device.parent), "w0"); + eth_device_linkchange(&rw009_wifi_device.parent, RT_FALSE); return RT_EOK; } @@ -594,9 +733,115 @@ void spi_wifi_isr(int vector) /* enter interrupt */ rt_interrupt_enter(); - WIFI_DEBUG("spi_wifi_isr\n"); + SPI_DEBUG("spi_wifi_isr\n"); rt_event_send(&spi_wifi_data_event, 1); /* leave interrupt */ rt_interrupt_leave(); } + +/********************************* RW009 tools **************************************/ +rt_err_t rw009_join(const char * SSID, const char * passwd) +{ + rt_err_t result; + rt_device_t wifi_device; + rw009_cmd_easy_join easy_join; + + wifi_device = rt_device_find("w0"); + if(wifi_device == RT_NULL) + return -RT_ENOSYS; + + strncpy( easy_join.ssid, SSID, sizeof(easy_join.ssid) ); + strncpy( easy_join.passwd, passwd, sizeof(easy_join.passwd) ); + + result = rt_device_control(wifi_device, + RW009_CMD_EASY_JOIN, + (void *)&easy_join); + + return result; +} + +rt_err_t rw009_softap(const char * SSID, const char * passwd,uint32_t security,uint32_t channel) +{ + rt_err_t result; + rt_device_t wifi_device; + rw009_cmd_softap softap; + + wifi_device = rt_device_find("w0"); + if(wifi_device == RT_NULL) + return -RT_ENOSYS; + + strncpy( softap.ssid, SSID, sizeof(softap.ssid) ); + strncpy( softap.passwd, passwd, sizeof(softap.passwd) ); + + softap.security = security; + softap.channel = channel; + result = rt_device_control(wifi_device, + RW009_CMD_SOFTAP, + (void *)&softap); + + return result; +} + +int32_t rw009_rssi(void) +{ + rt_err_t result; + struct rw009_wifi * wifi_device; + + wifi_device = (struct rw009_wifi *)rt_device_find("w0"); + + if(wifi_device == RT_NULL) + return 0; + + if(wifi_device->active == 0) + return 0; + + // SCAN + result = rt_device_control((rt_device_t)wifi_device, + RW009_CMD_RSSI, + RT_NULL); + + if(result == RT_EOK) + { + return wifi_device->ap_info.rssi; + } + + return 0; +} + +#ifdef RT_USING_FINSH +#include <finsh.h> + +static rt_err_t rw009_scan(void) +{ + rt_err_t result; + struct rw009_wifi * wifi_device; + + wifi_device = (struct rw009_wifi *)rt_device_find("w0"); + + rt_kprintf("\nCMD RW009_CMD_SCAN \n"); + result = rt_device_control((rt_device_t)wifi_device, + RW009_CMD_SCAN, + RT_NULL); + + rt_kprintf("CMD RW009_CMD_SCAN result:%d\n", result); + + if(result == RT_EOK) + { + uint32_t i; + rw009_ap_info *ap_info; + + for(i=0; i<wifi_device->ap_scan_count; i++) + { + ap_info = &wifi_device->ap_scan[i]; + rt_kprintf("AP #%02d SSID: %-32.32s\n", i, ap_info->ssid ); + } + } + + return result; +} +FINSH_FUNCTION_EXPORT(rw009_scan, SACN and list AP.); +FINSH_FUNCTION_EXPORT(rw009_join, RW009 join to AP.); +FINSH_FUNCTION_EXPORT(rw009_rssi, get RW009 current AP rssi.); + +#endif // RT_USING_FINSH diff --git a/components/drivers/spi/spi_wifi_rw009.h b/components/drivers/spi/spi_wifi_rw009.h index bb6fea5b01..4b684b9b24 100644 --- a/components/drivers/spi/spi_wifi_rw009.h +++ b/components/drivers/spi/spi_wifi_rw009.h @@ -20,6 +20,7 @@ * Change Logs: * Date Author Notes * 2014-07-31 aozima the first version + * 2014-09-18 aozima update command & response. */ #ifndef SPI_WIFI_H_INCLUDED @@ -28,7 +29,7 @@ #include <stdint.h> // little-endian -struct cmd_request +struct spi_cmd_request { uint32_t flag; uint32_t M2S_len; // master to slave data len. @@ -42,7 +43,7 @@ struct cmd_request #define CMD_FLAG_MRDY (0x01) // little-endian -struct response +struct spi_response { uint32_t flag; uint32_t S2M_len; // slave to master data len. @@ -55,20 +56,16 @@ struct response #define RESP_MAGIC2 (0x10325476) /* spi slave configure. */ -#define MAX_DATA_LEN 1520 +#define SPI_MAX_DATA_LEN 1520 #define SPI_TX_POOL_SIZE 2 #define SPI_RX_POOL_SIZE 2 -// align check -#if (MAX_DATA_LEN & 0x03) != 0 -#error MAX_DATA_LEN must ALIGN to 4byte! -#endif - typedef enum { data_type_eth_data = 0, data_type_cmd, data_type_resp, + data_type_status, } app_data_type_typedef; @@ -76,52 +73,154 @@ struct spi_data_packet { uint32_t data_len; uint32_t data_type; - char buffer[MAX_DATA_LEN]; + char buffer[SPI_MAX_DATA_LEN]; }; -/* tools */ -#define node_entry(node, type, member) \ - ((type *)((char *)(node) - (unsigned long)(&((type *)0)->member))) -#define member_offset(type, member) \ - ((unsigned long)(&((type *)0)->member)) +/********************************* RW009 **************************************/ -#define MAX_SPI_PACKET_SIZE (member_offset(struct spi_data_packet, buffer) + MAX_DATA_LEN) +/* option */ +#define RW009_CMD_TIMEOUT (RT_TICK_PER_SECOND*3) +#define SSID_NAME_LENGTH_MAX (32) +#define PASSWORD_LENGTH_MAX (64) -/********************************* RW009 **************************************/ +typedef enum +{ + MODE_STATION=0, + MODE_SOFTAP=1, +} wifi_mode_t; -struct spi_wifi_cmd +typedef struct _rw009_ap_info +{ + char ssid[SSID_NAME_LENGTH_MAX]; + uint8_t bssid[8]; // 6byte + 2byte PAD. + int rssi; /* Receive Signal Strength Indication in dBm. */ + uint32_t max_data_rate; /* Maximum data rate in kilobits/s */ + uint32_t security; /* Security type */ + uint32_t channel; /* Radio channel that the AP beacon was received on */ +} rw009_ap_info; + +typedef struct _rw009_cmd_init +{ + uint32_t mode; +} rw009_cmd_init; + +typedef struct _rw009_resp_init +{ + uint8_t mac[8]; // 6byte + 2byte PAD. + uint8_t sn[24]; // serial. + char version[16]; // firmware version. +} rw009_resp_init; + +typedef struct _rw009_cmd_easy_join +{ + char ssid[SSID_NAME_LENGTH_MAX]; + char passwd[PASSWORD_LENGTH_MAX]; +} rw009_cmd_easy_join; + +typedef struct _rw009_cmd_join +{ + uint8_t bssid[8]; // 6byte + 2byte PAD. + char passwd[PASSWORD_LENGTH_MAX]; +} rw009_cmd_join; + +typedef struct _rw009_cmd_rssi +{ + uint8_t bssid[8]; // 6byte + 2byte PAD. +} rw009_cmd_rssi; + +typedef struct _rw009_cmd_softap +{ + char ssid[SSID_NAME_LENGTH_MAX]; + char passwd[PASSWORD_LENGTH_MAX]; + + uint32_t security; /* Security type. */ + uint32_t channel; /* Radio channel that the AP beacon was received on */ +} rw009_cmd_softap; + +typedef struct _rw009_resp_join +{ + rw009_ap_info ap_info; +} rw009_resp_join; + +struct rw009_cmd { uint32_t cmd; - char buffer[128]; + uint32_t len; + + /** command body */ + union + { + rw009_cmd_init init; + rw009_cmd_easy_join easy_join; + rw009_cmd_join join; + rw009_cmd_rssi rssi; + rw009_cmd_softap softap; + } params; }; -struct spi_wifi_resp +struct rw009_resp { uint32_t cmd; - char buffer[128]; + uint32_t len; + + int32_t result; // result for CMD. + + /** resp Body */ + union + { + rw009_resp_init init; + rw009_ap_info ap_info; + } resp; }; -#define SPI_WIFI_CMD_INIT 128 //wait -#define SPI_WIFI_CMD_SCAN 129 //no wait -#define SPI_WIFI_CMD_JOIN 130 //no wait +#define RW009_CMD_INIT 128 +#define RW009_CMD_SCAN 129 +#define RW009_CMD_JOIN 130 +#define RW009_CMD_EASY_JOIN 131 +#define RW009_CMD_RSSI 132 +#define RW009_CMD_SOFTAP 133 + +/** cond !ADDTHIS*/ +#define SHARED_ENABLED 0x00008000 +#define WPA_SECURITY 0x00200000 +#define WPA2_SECURITY 0x00400000 +#define WPS_ENABLED 0x10000000 +#define WEP_ENABLED 0x0001 +#define TKIP_ENABLED 0x0002 +#define AES_ENABLED 0x0004 +#define WSEC_SWFLAG 0x0008 +/** endcond */ +/** + * Enumeration of Wi-Fi security modes + */ +typedef enum +{ + SECURITY_OPEN = 0, /**< Open security */ + SECURITY_WEP_PSK = WEP_ENABLED, /**< WEP Security with open authentication */ + SECURITY_WEP_SHARED = ( WEP_ENABLED | SHARED_ENABLED ), /**< WEP Security with shared authentication */ + SECURITY_WPA_TKIP_PSK = ( WPA_SECURITY | TKIP_ENABLED ), /**< WPA Security with TKIP */ + SECURITY_WPA_AES_PSK = ( WPA_SECURITY | AES_ENABLED ), /**< WPA Security with AES */ + SECURITY_WPA2_AES_PSK = ( WPA2_SECURITY | AES_ENABLED ), /**< WPA2 Security with AES */ + SECURITY_WPA2_TKIP_PSK = ( WPA2_SECURITY | TKIP_ENABLED ), /**< WPA2 Security with TKIP */ + SECURITY_WPA2_MIXED_PSK = ( WPA2_SECURITY | AES_ENABLED | TKIP_ENABLED ), /**< WPA2 Security with AES & TKIP */ + + SECURITY_WPS_OPEN = WPS_ENABLED, /**< WPS with open security */ + SECURITY_WPS_SECURE = (WPS_ENABLED | AES_ENABLED), /**< WPS with AES security */ + + SECURITY_UNKNOWN = -1, /**< May be returned by scan function if security is unknown. Do not pass this to the join function! */ + + SECURITY_FORCE_32_BIT = 0x7fffffff /**< Exists only to force wiced_security_t type to 32 bits */ +} security_t; /* porting */ extern void spi_wifi_hw_init(void); extern void spi_wifi_int_cmd(rt_bool_t cmd); extern rt_bool_t spi_wifi_is_busy(void); -#define SSID_NAME_LENGTH_MAX (32) -#define PASSWORD_LENGTH_MAX (32) - -struct cmd_join -{ - char ssid[SSID_NAME_LENGTH_MAX]; - char passwd[PASSWORD_LENGTH_MAX]; - - uint8_t bssid[8]; // 6byte + 2byte PAD. - - uint32_t channel; - uint32_t security; -}; +/* export API. */ +extern rt_err_t rt_hw_wifi_init(const char *spi_device_name,wifi_mode_t mode); +extern int32_t rw009_rssi(void); +extern rt_err_t rw009_join(const char * SSID, const char * passwd); +extern rt_err_t rw009_softap(const char * SSID, const char * passwd,uint32_t security,uint32_t channel); #endif // SPI_WIFI_H_INCLUDED diff --git a/components/drivers/src/completion.c b/components/drivers/src/completion.c index f49e44c48f..48afc2ee34 100644 --- a/components/drivers/src/completion.c +++ b/components/drivers/src/completion.c @@ -95,10 +95,10 @@ rt_err_t rt_completion_wait(struct rt_completion *completion, result = thread->error; level = rt_hw_interrupt_disable(); - /* clean completed flag */ - completion->flag = RT_UNCOMPLETED; } } + /* clean completed flag */ + completion->flag = RT_UNCOMPLETED; __exit: rt_hw_interrupt_enable(level); 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; diff --git a/components/drivers/usb/usbhost/class/adk.c b/components/drivers/usb/usbhost/class/adk.c index fd6619599c..1481d27ea6 100644 --- a/components/drivers/usb/usbhost/class/adk.c +++ b/components/drivers/usb/usbhost/class/adk.c @@ -67,7 +67,7 @@ RTM_EXPORT(rt_usbh_adk_set_string); */ static rt_err_t rt_usbh_adk_get_protocol(struct uintf* intf, rt_uint16_t *protocol) { - struct ureqest setup; + struct urequest setup; uinst_t device; int timeout = 100; @@ -101,7 +101,7 @@ static rt_err_t rt_usbh_adk_get_protocol(struct uintf* intf, rt_uint16_t *protoc static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index, const char* str) { - struct ureqest setup; + struct urequest setup; uinst_t device; int timeout = 100; @@ -134,7 +134,7 @@ static rt_err_t rt_usbh_adk_send_string(struct uintf* intf, rt_uint16_t index, */ static rt_err_t rt_usbh_adk_start(struct uintf* intf) { - struct ureqest setup; + struct urequest setup; uinst_t device; int timeout = 100; diff --git a/components/drivers/usb/usbhost/core/core.c b/components/drivers/usb/usbhost/core/core.c index af53370f4b..144358a4d3 100644 --- a/components/drivers/usb/usbhost/core/core.c +++ b/components/drivers/usb/usbhost/core/core.c @@ -246,7 +246,7 @@ rt_err_t rt_usbh_detach_instance(uinst_t device) rt_err_t rt_usbh_get_descriptor(uinst_t device, rt_uint8_t type, void* buffer, int nbytes) { - struct ureqest setup; + struct urequest setup; int timeout = 100; RT_ASSERT(device != RT_NULL); @@ -272,7 +272,7 @@ rt_err_t rt_usbh_get_descriptor(uinst_t device, rt_uint8_t type, void* buffer, */ rt_err_t rt_usbh_set_address(uinst_t device) { - struct ureqest setup; + struct urequest setup; int timeout = 100; RT_ASSERT(device != RT_NULL); @@ -306,7 +306,7 @@ rt_err_t rt_usbh_set_address(uinst_t device) */ rt_err_t rt_usbh_set_configure(uinst_t device, int config) { - struct ureqest setup; + struct urequest setup; int timeout = 100; /* check parameter */ @@ -335,7 +335,7 @@ rt_err_t rt_usbh_set_configure(uinst_t device, int config) */ rt_err_t rt_usbh_set_interface(uinst_t device, int intf) { - struct ureqest setup; + struct urequest setup; int timeout = 100; /* check parameter */ @@ -364,7 +364,7 @@ rt_err_t rt_usbh_set_interface(uinst_t device, int intf) */ rt_err_t rt_usbh_clear_feature(uinst_t device, int endpoint, int feature) { - struct ureqest setup; + struct urequest setup; int timeout = 100; /* check parameter */ diff --git a/components/drivers/usb/usbhost/core/hub.c b/components/drivers/usb/usbhost/core/hub.c index a71aa4f89c..bde316ae77 100644 --- a/components/drivers/usb/usbhost/core/hub.c +++ b/components/drivers/usb/usbhost/core/hub.c @@ -43,7 +43,7 @@ static struct uclass_driver hub_driver; rt_err_t rt_usbh_hub_get_descriptor(struct uinstance* device, rt_uint8_t *buffer, rt_size_t nbytes) { - struct ureqest setup; + struct urequest setup; int timeout = 100; /* parameter check */ @@ -72,7 +72,7 @@ rt_err_t rt_usbh_hub_get_descriptor(struct uinstance* device, rt_uint8_t *buffer */ rt_err_t rt_usbh_hub_get_status(struct uinstance* device, rt_uint8_t* buffer) { - struct ureqest setup; + struct urequest setup; int timeout = 100; int length = 4; @@ -104,7 +104,7 @@ rt_err_t rt_usbh_hub_get_status(struct uinstance* device, rt_uint8_t* buffer) rt_err_t rt_usbh_hub_get_port_status(uhub_t hub, rt_uint16_t port, rt_uint8_t* buffer) { - struct ureqest setup; + struct urequest setup; int timeout = 100; int length = 4; @@ -144,7 +144,7 @@ rt_err_t rt_usbh_hub_get_port_status(uhub_t hub, rt_uint16_t port, rt_err_t rt_usbh_hub_clear_port_feature(uhub_t hub, rt_uint16_t port, rt_uint16_t feature) { - struct ureqest setup; + struct urequest setup; int timeout = 100; /* parameter check */ @@ -183,7 +183,7 @@ rt_err_t rt_usbh_hub_clear_port_feature(uhub_t hub, rt_uint16_t port, rt_err_t rt_usbh_hub_set_port_feature(uhub_t hub, rt_uint16_t port, rt_uint16_t feature) { - struct ureqest setup; + struct urequest setup; int timeout = 100; /* parameter check */ |
