diff options
| author | Man, Jianting (Meco) <[email protected]> | 2022-12-11 22:45:04 -0500 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-12-11 22:45:04 -0500 |
| commit | 8b5a501831c06c6bca74740565b3a9b6efb34c5f (patch) | |
| tree | de621de0642d876e1d62d5f370e54b1534150a7f /components/drivers/sensor | |
| parent | 99bdf978d7fe4ec18ed50a639e15b254825c871b (diff) | |
[sensor][cmd] add sensor_get_type/vender/unit_name functions (#6727)
* [sensor][cmd] add sensor_get_type/vender/unit_name functions
* rename sensor folder
Diffstat (limited to 'components/drivers/sensor')
| -rw-r--r-- | components/drivers/sensor/SConscript | 14 | ||||
| -rw-r--r-- | components/drivers/sensor/sensor.c | 491 | ||||
| -rw-r--r-- | components/drivers/sensor/sensor_cmd.c | 563 |
3 files changed, 1068 insertions, 0 deletions
diff --git a/components/drivers/sensor/SConscript b/components/drivers/sensor/SConscript new file mode 100644 index 0000000000..afafc6d2ce --- /dev/null +++ b/components/drivers/sensor/SConscript @@ -0,0 +1,14 @@ +# SConscript for sensor framework + +from building import * + +cwd = GetCurrentDir() +src = ['sensor.c'] +CPPPATH = [cwd, cwd + '/../include'] + +if GetDepend('RT_USING_SENSOR_CMD'): + src += ['sensor_cmd.c'] + +group = DefineGroup('DeviceDrivers', src, depend = ['RT_USING_SENSOR', 'RT_USING_DEVICE'], CPPPATH = CPPPATH) + +Return('group') diff --git a/components/drivers/sensor/sensor.c b/components/drivers/sensor/sensor.c new file mode 100644 index 0000000000..3a5a0421df --- /dev/null +++ b/components/drivers/sensor/sensor.c @@ -0,0 +1,491 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-31 flybreak first version + * 2020-02-22 luhuadong support custom commands + */ + +#include <drivers/sensor.h> + +#define DBG_TAG "sensor" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#include <string.h> + +static char *const sensor_name_str[] = +{ + "None", + "ac-", /* Accelerometer */ + "gy-", /* Gyroscope */ + "ma-", /* Magnetometer */ + "tm-", /* Temperature */ + "hm-", /* Relative Humidity */ + "br-", /* Barometer */ + "li-", /* Ambient light */ + "pr-", /* Proximity */ + "hr-", /* Heart Rate */ + "tv-", /* TVOC Level */ + "ni-", /* Noise Loudness */ + "st-", /* Step sensor */ + "fr-", /* Force sensor */ + "du-", /* Dust sensor */ + "ec-", /* eCO2 sensor */ + "gn-", /* GPS/GNSS sensor */ + "tf-", /* TOF sensor */ + "sp-", /* SpO2 sensor */ + "ia-", /* IAQ sensor */ + "et-", /* EtOH sensor */ + "bp-" /* Blood Pressure */ +}; + +/* sensor interrupt handler function */ +static void _sensor_cb(rt_sensor_t sen) +{ + if (sen->parent.rx_indicate == RT_NULL) + { + return; + } + + if (sen->irq_handle != RT_NULL) + { + sen->irq_handle(sen); + } + + /* The buffer is not empty. Read the data in the buffer first */ + if (sen->data_len > 0) + { + sen->parent.rx_indicate(&sen->parent, sen->data_len / sizeof(struct rt_sensor_data)); + } + else if (sen->config.mode == RT_SENSOR_MODE_INT) + { + /* The interrupt mode only produces one data at a time */ + sen->parent.rx_indicate(&sen->parent, 1); + } + else if (sen->config.mode == RT_SENSOR_MODE_FIFO) + { + sen->parent.rx_indicate(&sen->parent, sen->info.fifo_max); + } +} + +/* ISR for sensor interrupt */ +static void _irq_callback(void *args) +{ + rt_sensor_t sensor = (rt_sensor_t)args; + rt_uint8_t i; + + if (sensor->module) + { + /* Invoke a callback for all sensors in the module */ + for (i = 0; i < sensor->module->sen_num; i++) + { + _sensor_cb(sensor->module->sen[i]); + } + } + else + { + _sensor_cb(sensor); + } +} + +/* Sensor interrupt initialization function */ +static rt_err_t _sensor_irq_init(rt_sensor_t sensor) +{ + if (sensor->config.irq_pin.pin == RT_PIN_NONE) + { + return -RT_EINVAL; + } + + rt_pin_mode(sensor->config.irq_pin.pin, sensor->config.irq_pin.mode); + + if (sensor->config.irq_pin.mode == PIN_MODE_INPUT_PULLDOWN) + { + rt_pin_attach_irq(sensor->config.irq_pin.pin, PIN_IRQ_MODE_RISING, _irq_callback, (void *)sensor); + } + else if (sensor->config.irq_pin.mode == PIN_MODE_INPUT_PULLUP) + { + rt_pin_attach_irq(sensor->config.irq_pin.pin, PIN_IRQ_MODE_FALLING, _irq_callback, (void *)sensor); + } + else if (sensor->config.irq_pin.mode == PIN_MODE_INPUT) + { + rt_pin_attach_irq(sensor->config.irq_pin.pin, PIN_IRQ_MODE_RISING_FALLING, _irq_callback, (void *)sensor); + } + + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_TRUE); + + LOG_I("interrupt init success"); + + return 0; +} + +/* sensor local ops */ +static rt_ssize_t _local_fetch_data(rt_sensor_t sensor, rt_sensor_data_t buf, rt_size_t len) +{ + LOG_D("Undefined fetch_data"); + return -RT_EINVAL; +} +static rt_err_t _local_control(rt_sensor_t sensor, int cmd, void *arg) +{ + LOG_D("Undefined control"); + return -RT_EINVAL; +} +static struct rt_sensor_ops local_ops = +{ + .fetch_data = _local_fetch_data, + .control = _local_control +}; + +/* RT-Thread Device Interface */ +static rt_err_t _sensor_open(rt_device_t dev, rt_uint16_t oflag) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + RT_ASSERT(dev != RT_NULL); + rt_err_t res = RT_EOK; + rt_err_t (*local_ctrl)(rt_sensor_t sensor, int cmd, void *arg) = _local_control; + + if (sensor->module) + { + /* take the module mutex */ + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + + if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf == RT_NULL) + { + /* Allocate memory for the sensor buffer */ + sensor->data_buf = rt_malloc(sizeof(struct rt_sensor_data) * sensor->info.fifo_max); + if (sensor->data_buf == RT_NULL) + { + res = -RT_ENOMEM; + goto __exit; + } + } + if (sensor->ops->control != RT_NULL) + { + local_ctrl = sensor->ops->control; + } + + sensor->config.mode = RT_SENSOR_MODE_POLLING; + if (oflag & RT_DEVICE_FLAG_RDONLY && dev->flag & RT_DEVICE_FLAG_RDONLY) + { + /* If polling mode is supported, configure it to polling mode */ + local_ctrl(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_POLLING); + } + else if (oflag & RT_DEVICE_FLAG_INT_RX && dev->flag & RT_DEVICE_FLAG_INT_RX) + { + /* If interrupt mode is supported, configure it to interrupt mode */ + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_INT) == RT_EOK) + { + /* Initialization sensor interrupt */ + _sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_INT; + } + } + else if (oflag & RT_DEVICE_FLAG_FIFO_RX && dev->flag & RT_DEVICE_FLAG_FIFO_RX) + { + /* If fifo mode is supported, configure it to fifo mode */ + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_MODE, (void *)RT_SENSOR_MODE_FIFO) == RT_EOK) + { + /* Initialization sensor interrupt */ + _sensor_irq_init(sensor); + sensor->config.mode = RT_SENSOR_MODE_FIFO; + } + } + else + { + res = -RT_EINVAL; + goto __exit; + } + + /* Configure power mode to normal mode */ + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_NORMAL) == RT_EOK) + { + sensor->config.power = RT_SENSOR_POWER_NORMAL; + } + +__exit: + if (sensor->module) + { + /* release the module mutex */ + rt_mutex_release(sensor->module->lock); + } + + return res; +} + +static rt_err_t _sensor_close(rt_device_t dev) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + int i; + rt_err_t (*local_ctrl)(rt_sensor_t sensor, int cmd, void *arg) = _local_control; + + RT_ASSERT(dev != RT_NULL); + + if (sensor->module) + { + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + if (sensor->ops->control != RT_NULL) + { + local_ctrl = sensor->ops->control; + } + + /* Configure power mode to power down mode */ + if (local_ctrl(sensor, RT_SENSOR_CTRL_SET_POWER, (void *)RT_SENSOR_POWER_DOWN) == RT_EOK) + { + sensor->config.power = RT_SENSOR_POWER_DOWN; + } + + if (sensor->module != RT_NULL && sensor->info.fifo_max > 0 && sensor->data_buf != RT_NULL) + { + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->parent.ref_count > 0) + goto __exit; + } + + /* Free memory for the sensor buffer */ + for (i = 0; i < sensor->module->sen_num; i ++) + { + if (sensor->module->sen[i]->data_buf) + { + rt_free(sensor->module->sen[i]->data_buf); + sensor->module->sen[i]->data_buf = RT_NULL; + } + } + } + if (sensor->config.mode != RT_SENSOR_MODE_POLLING) + { + /* Sensor disable interrupt */ + if (sensor->config.irq_pin.pin != RT_PIN_NONE) + { + rt_pin_irq_enable(sensor->config.irq_pin.pin, RT_FALSE); + } + } + +__exit: + if (sensor->module) + { + rt_mutex_release(sensor->module->lock); + } + + return RT_EOK; +} + +static rt_size_t _sensor_read(rt_device_t dev, rt_off_t pos, void *buf, rt_size_t len) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + rt_size_t result = 0; + RT_ASSERT(dev != RT_NULL); + + if (buf == NULL || len == 0) + { + return 0; + } + + if (sensor->module) + { + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + + /* The buffer is not empty. Read the data in the buffer first */ + if (sensor->data_len > 0) + { + if (len > sensor->data_len / sizeof(struct rt_sensor_data)) + { + len = sensor->data_len / sizeof(struct rt_sensor_data); + } + + rt_memcpy(buf, sensor->data_buf, len * sizeof(struct rt_sensor_data)); + + /* Clear the buffer */ + sensor->data_len = 0; + result = len; + } + else + { + /* If the buffer is empty, read the data */ + if (sensor->ops->fetch_data) + { + result = sensor->ops->fetch_data(sensor, buf, len); + } + } + + if (sensor->module) + { + rt_mutex_release(sensor->module->lock); + } + + return result; +} + +static rt_err_t _sensor_control(rt_device_t dev, int cmd, void *args) +{ + rt_sensor_t sensor = (rt_sensor_t)dev; + rt_err_t result = RT_EOK; + RT_ASSERT(dev != RT_NULL); + rt_err_t (*local_ctrl)(rt_sensor_t sensor, int cmd, void *arg) = _local_control; + + if (sensor->module) + { + rt_mutex_take(sensor->module->lock, RT_WAITING_FOREVER); + } + if (sensor->ops->control != RT_NULL) + { + local_ctrl = sensor->ops->control; + } + + switch (cmd) + { + case RT_SENSOR_CTRL_GET_ID: + if (args) + { + result = local_ctrl(sensor, RT_SENSOR_CTRL_GET_ID, args); + } + break; + case RT_SENSOR_CTRL_GET_INFO: + if (args) + { + rt_memcpy(args, &sensor->info, sizeof(struct rt_sensor_info)); + } + break; + case RT_SENSOR_CTRL_SET_RANGE: + /* Configuration measurement range */ + result = local_ctrl(sensor, RT_SENSOR_CTRL_SET_RANGE, args); + if (result == RT_EOK) + { + sensor->config.range = (rt_int32_t)args; + LOG_D("set range %d", sensor->config.range); + } + break; + case RT_SENSOR_CTRL_SET_ODR: + /* Configuration data output rate */ + result = local_ctrl(sensor, RT_SENSOR_CTRL_SET_ODR, args); + if (result == RT_EOK) + { + sensor->config.odr = (rt_uint32_t)args & 0xFFFF; + LOG_D("set odr %d", sensor->config.odr); + } + break; + case RT_SENSOR_CTRL_SET_POWER: + /* Configuration sensor power mode */ + result = local_ctrl(sensor, RT_SENSOR_CTRL_SET_POWER, args); + if (result == RT_EOK) + { + sensor->config.power = (rt_uint32_t)args & 0xFF; + LOG_D("set power mode code:", sensor->config.power); + } + break; + case RT_SENSOR_CTRL_SELF_TEST: + /* Device self-test */ + result = local_ctrl(sensor, RT_SENSOR_CTRL_SELF_TEST, args); + break; + default: + + if (cmd > RT_SENSOR_CTRL_USER_CMD_START) + { + /* Custom commands */ + result = local_ctrl(sensor, cmd, args); + } + else + { + result = -RT_ERROR; + } + break; + } + + if (sensor->module) + { + rt_mutex_release(sensor->module->lock); + } + + return result; +} + +#ifdef RT_USING_DEVICE_OPS +const static struct rt_device_ops rt_sensor_ops = +{ + RT_NULL, + _sensor_open, + _sensor_close, + _sensor_read, + RT_NULL, + _sensor_control +}; +#endif + + +/* + * sensor register + */ +int rt_hw_sensor_register(rt_sensor_t sensor, + const char *name, + rt_uint32_t flag, + void *data) +{ + rt_int8_t result; + rt_device_t device; + RT_ASSERT(sensor != RT_NULL); + + char *sensor_name = RT_NULL, *device_name = RT_NULL; + + if (sensor->ops == RT_NULL) + { + sensor->ops = &local_ops; + } + + /* Add a type name for the sensor device */ + sensor_name = sensor_name_str[sensor->info.type]; + device_name = (char *)rt_calloc(1, rt_strlen(sensor_name) + 1 + rt_strlen(name)); + if (device_name == RT_NULL) + { + LOG_E("device_name calloc failed!"); + return -RT_ERROR; + } + + rt_memcpy(device_name, sensor_name, rt_strlen(sensor_name) + 1); + strcat(device_name, name); + + if (sensor->module != RT_NULL && sensor->module->lock == RT_NULL) + { + /* Create a mutex lock for the module */ + sensor->module->lock = rt_mutex_create(name, RT_IPC_FLAG_PRIO); + if (sensor->module->lock == RT_NULL) + { + rt_free(device_name); + return -RT_ERROR; + } + } + + device = &sensor->parent; + +#ifdef RT_USING_DEVICE_OPS + device->ops = &rt_sensor_ops; +#else + device->init = RT_NULL; + device->open = _sensor_open; + device->close = _sensor_close; + device->read = _sensor_read; + device->write = RT_NULL; + device->control = _sensor_control; +#endif + device->type = RT_Device_Class_Sensor; + device->rx_indicate = RT_NULL; + device->tx_complete = RT_NULL; + device->user_data = data; + + result = rt_device_register(device, device_name, flag | RT_DEVICE_FLAG_STANDALONE); + if (result != RT_EOK) + { + LOG_E("sensor[%s] register err code: %d", device_name, result); + rt_free(device_name); + return result; + } + + LOG_I("sensor[%s] init success", device_name); + rt_free(device_name); + return RT_EOK; +} diff --git a/components/drivers/sensor/sensor_cmd.c b/components/drivers/sensor/sensor_cmd.c new file mode 100644 index 0000000000..7c45c3dac1 --- /dev/null +++ b/components/drivers/sensor/sensor_cmd.c @@ -0,0 +1,563 @@ +/* + * Copyright (c) 2006-2021, RT-Thread Development Team + * + * SPDX-License-Identifier: Apache-2.0 + * + * Change Logs: + * Date Author Notes + * 2019-01-31 flybreak first version + * 2019-07-16 WillianChan Increase the output of sensor information + * 2020-02-22 luhuadong Add vendor info and sensor types for cmd + */ + +#include <drivers/sensor.h> + +#define DBG_TAG "sensor.cmd" +#define DBG_LVL DBG_INFO +#include <rtdbg.h> + +#include <stdlib.h> +#include <string.h> + +static rt_sem_t sensor_rx_sem = RT_NULL; + +static const char *sensor_get_type_name(rt_sensor_info_t info) +{ + switch(info->type) + { + case RT_SENSOR_CLASS_ACCE: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_ACCE); + case RT_SENSOR_CLASS_GYRO: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_GYRO); + case RT_SENSOR_CLASS_MAG: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_MAG); + case RT_SENSOR_CLASS_TEMP: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_TEMP); + case RT_SENSOR_CLASS_HUMI: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_HUMI); + case RT_SENSOR_CLASS_BARO: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_BARO); + case RT_SENSOR_CLASS_LIGHT: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_LIGHT); + case RT_SENSOR_CLASS_PROXIMITY: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_PROXIMITY); + case RT_SENSOR_CLASS_HR: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_HR); + case RT_SENSOR_CLASS_TVOC: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_TVOC); + case RT_SENSOR_CLASS_NOISE: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_NOISE); + case RT_SENSOR_CLASS_STEP: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_STEP); + case RT_SENSOR_CLASS_FORCE: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_FORCE); + case RT_SENSOR_CLASS_DUST: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_DUST); + case RT_SENSOR_CLASS_ECO2: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_ECO2); + case RT_SENSOR_CLASS_GNSS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_GNSS); + case RT_SENSOR_CLASS_TOF: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_TOF); + case RT_SENSOR_CLASS_SPO2: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_SPO2); + case RT_SENSOR_CLASS_IAQ: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_IAQ); + case RT_SENSOR_CLASS_ETOH: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_ETOH); + case RT_SENSOR_CLASS_BP: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_BP); + case RT_SENSOR_CLASS_NONE: + default: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_CLASS_NONE); + } +} + +static const char *sensor_get_vendor_name(rt_sensor_info_t info) +{ + switch(info->vendor) + { + case RT_SENSOR_VENDOR_STM: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_STM); + case RT_SENSOR_VENDOR_BOSCH: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_BOSCH); + case RT_SENSOR_VENDOR_INVENSENSE: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_INVENSENSE); + case RT_SENSOR_VENDOR_SEMTECH: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_SEMTECH); + case RT_SENSOR_VENDOR_GOERTEK: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_GOERTEK); + case RT_SENSOR_VENDOR_MIRAMEMS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_MIRAMEMS); + case RT_SENSOR_VENDOR_DALLAS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_DALLAS); + case RT_SENSOR_VENDOR_ASAIR: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_ASAIR); + case RT_SENSOR_VENDOR_SHARP: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_SHARP); + case RT_SENSOR_VENDOR_SENSIRION: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_SENSIRION); + case RT_SENSOR_VENDOR_TI: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_TI); + case RT_SENSOR_VENDOR_PLANTOWER: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_PLANTOWER); + case RT_SENSOR_VENDOR_AMS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_AMS); + case RT_SENSOR_VENDOR_MAXIM: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_MAXIM); + case RT_SENSOR_VENDOR_MELEXIS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_MELEXIS); + case RT_SENSOR_VENDOR_UNKNOWN: + default: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_VENDOR_UNKNOWN); + } +} + +static const char *sensor_get_unit_name(rt_sensor_info_t info) +{ + switch(info->unit) + { + case RT_SENSOR_UNIT_MG: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MG); + case RT_SENSOR_UNIT_MDPS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MDPS); + case RT_SENSOR_UNIT_MGAUSS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MGAUSS); + case RT_SENSOR_UNIT_LUX: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_LUX); + case RT_SENSOR_UNIT_CM: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_CM); + case RT_SENSOR_UNIT_MM: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MM); + case RT_SENSOR_UNIT_PA: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_PA); + case RT_SENSOR_UNIT_MMHG: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MMHG); + case RT_SENSOR_UNIT_PERMILLAGE: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_PERMILLAGE); + case RT_SENSOR_UNIT_PERCENTAGE: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_PERCENTAGE); + case RT_SENSOR_UNIT_CELSIUS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_CELSIUS); + case RT_SENSOR_UNIT_FAHRENHEIT: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_FAHRENHEIT); + case RT_SENSOR_UNIT_KELVIN: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_KELVIN); + case RT_SENSOR_UNIT_HZ: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_HZ); + case RT_SENSOR_UNIT_BPM: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_BPM); + case RT_SENSOR_UNIT_MN: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MN); + case RT_SENSOR_UNIT_N: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_N); + case RT_SENSOR_UNIT_PPM: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_PPM); + case RT_SENSOR_UNIT_PPB: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_PPB); + case RT_SENSOR_UNIT_DMS: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_DMS); + case RT_SENSOR_UNIT_DD: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_DD); + case RT_SENSOR_UNIT_MGM3: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_MGM3); + case RT_SENSOR_UNIT_NONE: + default: + return RT_SENSOR_MACRO_GET_NAME(RT_SENSOR_UNIT_NONE); + } +} + +static void sensor_show_data(rt_size_t num, rt_sensor_t sensor, struct rt_sensor_data *sensor_data) +{ + const char *unit_name = sensor_get_unit_name(&sensor->info); + switch (sensor->info.type) + { + case RT_SENSOR_CLASS_ACCE: + LOG_I("num:%d, x:%f, y:%f, z:%f %s, timestamp:%u", num, sensor_data->data.acce.x, sensor_data->data.acce.y, sensor_data->data.acce.z, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_GYRO: + LOG_I("num:%d, x:%f, y:%f, z:%f %s, timestamp:%u", num, sensor_data->data.gyro.x, sensor_data->data.gyro.y, sensor_data->data.gyro.z, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_MAG: + LOG_I("num:%d, x:%f, y:%f, z:%f %s, timestamp:%u", num, sensor_data->data.mag.x, sensor_data->data.mag.y, sensor_data->data.mag.z, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_GNSS: + LOG_I("num:%d, lon:%f, lat:%f %s, timestamp:%u", num, sensor_data->data.coord.longitude, sensor_data->data.coord.latitude, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_TEMP: + LOG_I("num:%d, temp:%f%s, timestamp:%u", num, sensor_data->data.temp, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_HUMI: + LOG_I("num:%d, humi:%f%s, timestamp:%u", num, sensor_data->data.humi, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_BARO: + LOG_I("num:%d, press:%f%s, timestamp:%u", num, sensor_data->data.baro, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_LIGHT: + LOG_I("num:%d, light:%f%s, timestamp:%u", num, sensor_data->data.light, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_PROXIMITY: + case RT_SENSOR_CLASS_TOF: + LOG_I("num:%d, distance:%f%s, timestamp:%u", num, sensor_data->data.proximity, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_HR: + LOG_I("num:%d, heart rate:%f%s, timestamp:%u", num, sensor_data->data.hr, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_TVOC: + LOG_I("num:%d, tvoc:%f%s, timestamp:%u", num, sensor_data->data.tvoc, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_NOISE: + LOG_I("num:%d, noise:%f%s, timestamp:%u", num, sensor_data->data.noise, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_STEP: + LOG_I("num:%d, step:%f%s, timestamp:%u", num, sensor_data->data.step, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_FORCE: + LOG_I("num:%d, force:%f%s, timestamp:%u", num, sensor_data->data.force, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_DUST: + LOG_I("num:%d, dust:%f%s, timestamp:%u", num, sensor_data->data.dust, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_ECO2: + LOG_I("num:%d, eco2:%f%s, timestamp:%u", num, sensor_data->data.eco2, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_IAQ: + LOG_I("num:%d, IAQ:%f%s, timestamp:%u", num, sensor_data->data.iaq, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_ETOH: + LOG_I("num:%d, EtOH:%f%s, timestamp:%u", num, sensor_data->data.etoh, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_BP: + LOG_I("num:%d, bp.sbp:%f, bp.dbp:%f %s, timestamp:%u", num, sensor_data->data.bp.sbp, sensor_data->data.bp.dbp, unit_name, sensor_data->timestamp); + break; + case RT_SENSOR_CLASS_NONE: + default: + LOG_E("Unknown type of sensor!"); + break; + } +} + +static rt_err_t rx_callback(rt_device_t dev, rt_size_t size) +{ + rt_sem_release(sensor_rx_sem); + return 0; +} + +static void sensor_fifo_rx_entry(void *parameter) +{ + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; + struct rt_sensor_data *data = RT_NULL; + struct rt_sensor_info info; + rt_size_t res, i; + + rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); + + data = (struct rt_sensor_data *)rt_malloc(sizeof(struct rt_sensor_data) * info.fifo_max); + if (data == RT_NULL) + { + LOG_E("Memory allocation failed!"); + } + + while (1) + { + rt_sem_take(sensor_rx_sem, RT_WAITING_FOREVER); + + res = rt_device_read(dev, 0, data, info.fifo_max); + for (i = 0; i < res; i++) + { + sensor_show_data(i, sensor, &data[i]); + } + } +} + +static void sensor_fifo(int argc, char **argv) +{ + static rt_thread_t tid1 = RT_NULL; + rt_device_t dev = RT_NULL; + rt_sensor_t sensor; + + dev = rt_device_find(argv[1]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + sensor = (rt_sensor_t)dev; + + if (rt_device_open(dev, RT_DEVICE_FLAG_FIFO_RX) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + + if (sensor_rx_sem == RT_NULL) + { + sensor_rx_sem = rt_sem_create("sen_rx_sem", 0, RT_IPC_FLAG_FIFO); + } + else + { + LOG_E("The thread is running, please reboot and try again"); + return; + } + + tid1 = rt_thread_create("sen_rx_thread", + sensor_fifo_rx_entry, sensor, + 1024, + 15, 5); + + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + rt_device_set_rx_indicate(dev, rx_callback); + + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)20); +} +#ifdef RT_USING_FINSH + MSH_CMD_EXPORT(sensor_fifo, Sensor fifo mode test function); +#endif + +static void sensor_irq_rx_entry(void *parameter) +{ + rt_device_t dev = (rt_device_t)parameter; + rt_sensor_t sensor = (rt_sensor_t)parameter; + struct rt_sensor_data data; + rt_size_t res, i = 0; + + while (1) + { + rt_sem_take(sensor_rx_sem, RT_WAITING_FOREVER); + + res = rt_device_read(dev, 0, &data, 1); + if (res == 1) + { + sensor_show_data(i++, sensor, &data); + } + } +} + +static void sensor_int(int argc, char **argv) +{ + static rt_thread_t tid1 = RT_NULL; + rt_device_t dev = RT_NULL; + rt_sensor_t sensor; + + dev = rt_device_find(argv[1]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + sensor = (rt_sensor_t)dev; + + if (sensor_rx_sem == RT_NULL) + { + sensor_rx_sem = rt_sem_create("sen_rx_sem", 0, RT_IPC_FLAG_FIFO); + } + else + { + LOG_E("The thread is running, please reboot and try again"); + return; + } + + tid1 = rt_thread_create("sen_rx_thread", + sensor_irq_rx_entry, sensor, + 1024, + 15, 5); + + if (tid1 != RT_NULL) + rt_thread_startup(tid1); + + rt_device_set_rx_indicate(dev, rx_callback); + + if (rt_device_open(dev, RT_DEVICE_FLAG_INT_RX) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)20); +} +#ifdef RT_USING_FINSH + MSH_CMD_EXPORT(sensor_int, Sensor interrupt mode test function); +#endif + +static void sensor_polling(int argc, char **argv) +{ + rt_uint16_t num = 10; + rt_device_t dev = RT_NULL; + rt_sensor_t sensor; + struct rt_sensor_data data; + rt_size_t res, i; + rt_int32_t delay; + rt_err_t result; + + dev = rt_device_find(argv[1]); + if (dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[1]); + return; + } + if (argc > 2) + num = atoi(argv[2]); + + sensor = (rt_sensor_t)dev; + delay = sensor->info.period_min > 100 ? sensor->info.period_min : 100; + + result = rt_device_open(dev, RT_DEVICE_FLAG_RDONLY); + if (result != RT_EOK) + { + LOG_E("open device failed! error code : %d", result); + return; + } + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100); + + for (i = 0; i < num; i++) + { + res = rt_device_read(dev, 0, &data, 1); + if (res != 1) + { + LOG_E("read data failed!size is %d", res); + } + else + { + sensor_show_data(i, sensor, &data); + } + rt_thread_mdelay(delay); + } + rt_device_close(dev); +} +#ifdef RT_USING_FINSH + MSH_CMD_EXPORT(sensor_polling, Sensor polling mode test function); +#endif + +static void sensor(int argc, char **argv) +{ + static rt_device_t dev = RT_NULL; + struct rt_sensor_data data; + rt_sensor_t sensor; + rt_size_t res, i; + rt_int32_t delay; + + /* If the number of arguments less than 2 */ + if (argc < 2) + { + rt_kprintf("\n"); + rt_kprintf("sensor [OPTION] [PARAM]\n"); + rt_kprintf(" probe <dev_name> Probe sensor by given name\n"); + rt_kprintf(" info Get sensor info\n"); + rt_kprintf(" range <var> Set range to var\n"); + rt_kprintf(" mode <var> Set work mode to var\n"); + rt_kprintf(" power <var> Set power mode to var\n"); + rt_kprintf(" rate <var> Set output date rate to var\n"); + rt_kprintf(" read [num] Read [num] times sensor (default 5)\n"); + return ; + } + else if (!strcmp(argv[1], "info")) + { + struct rt_sensor_info info; + if (dev == RT_NULL) + { + LOG_W("Please probe sensor device first!"); + return ; + } + rt_device_control(dev, RT_SENSOR_CTRL_GET_INFO, &info); + rt_kprintf("model :%s\n", info.model); + rt_kprintf("type: :%s\n", sensor_get_type_name(&info)); + rt_kprintf("vendor :%s\n", sensor_get_vendor_name(&info)); + rt_kprintf("unit :%s\n", sensor_get_unit_name(&info)); + rt_kprintf("range_max :%d\n", info.range_max); + rt_kprintf("range_min :%d\n", info.range_min); + rt_kprintf("period_min:%dms\n", info.period_min); + rt_kprintf("fifo_max :%d\n", info.fifo_max); + } + else if (!strcmp(argv[1], "read")) + { + rt_uint16_t num = 5; + + if (dev == RT_NULL) + { + LOG_W("Please probe sensor device first!"); + return ; + } + if (argc == 3) + { + num = atoi(argv[2]); + } + + sensor = (rt_sensor_t)dev; + delay = sensor->info.period_min > 100 ? sensor->info.period_min : 100; + + for (i = 0; i < num; i++) + { + res = rt_device_read(dev, 0, &data, 1); + if (res != 1) + { + LOG_E("read data failed!size is %d", res); + } + else + { + sensor_show_data(i, sensor, &data); + } + rt_thread_mdelay(delay); + } + } + else if (argc == 3) + { + if (!strcmp(argv[1], "probe")) + { + rt_uint8_t reg = 0xFF; + rt_device_t new_dev; + + new_dev = rt_device_find(argv[2]); + if (new_dev == RT_NULL) + { + LOG_E("Can't find device:%s", argv[2]); + return; + } + if (rt_device_open(new_dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) + { + LOG_E("open device failed!"); + return; + } + rt_device_control(new_dev, RT_SENSOR_CTRL_GET_ID, ®); + LOG_I("device id: 0x%x!", reg); + if (dev) + { + rt_device_close(dev); + } + dev = new_dev; + } + else if (dev == RT_NULL) + { + LOG_W("Please probe sensor first!"); + return ; + } + else if (!strcmp(argv[1], "range")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_RANGE, (void *)atoi(argv[2])); + } + else if (!strcmp(argv[1], "mode")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_MODE, (void *)atoi(argv[2])); + } + else if (!strcmp(argv[1], "power")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_POWER, (void *)atoi(argv[2])); + } + else if (!strcmp(argv[1], "rate")) + { + rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)atoi(argv[2])); + } + else + { + LOG_W("Unknown command, please enter 'sensor' get help information!"); + } + } + else + { + LOG_W("Unknown command, please enter 'sensor' get help information!"); + } +} +#ifdef RT_USING_FINSH + MSH_CMD_EXPORT(sensor, sensor test function); +#endif |
