Wiki

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revisionPrevious revision
Next revision
Previous revision
resources:tools-software:android-drivers:sensor-acceleration:adxl345 [09 Nov 2011 14:01] – Approved Michael Hennerichresources:tools-software:android-drivers:sensor-acceleration:adxl345 [11 Dec 2013 09:57] (current) – [Platform data configuration] Michael Hennerich
Line 71: Line 71:
 **The files can be downloaded here:**\\ **The files can be downloaded here:**\\
  
-[[bf>project/android/scmgit/|Android git]] +{{:resources:tools-software:android-drivers:sensor-acceleration:android_hardware.zip|}}
- +
-  * [[http://blackfin.uclinux.org/git/?p=android;a=blob_plain;f=hardware/sensors/sensors_adxl34x.c;hb=master|sensors_adxl34x.c]] +
-  * [[http://blackfin.uclinux.org/git/?p=android;a=blob_plain;f=hardware/sensors/Android.mk;hb=master|Android.mk]]+
  
 ---- ----
Line 98: Line 95:
 </code> </code>
  
-<note tip>+<WRAP tip>
 In case the ADXL345/6 is not always event0 you can alternatively approach via /sys/bus/i2c/devices/... In case the ADXL345/6 is not always event0 you can alternatively approach via /sys/bus/i2c/devices/...
-</note>+</WRAP>
  
   * Rebuilt your Android tree   * Rebuilt your Android tree
  
-<note tip>+<WRAP tip>
 Upon start the Android log file (use logcat) should include following lines: Upon start the Android log file (use logcat) should include following lines:
  
Line 112: Line 109:
 D/SensorManager( 2064): found sensor: Analog Devices ADXL345/6 3-axis Accelerometer, handle=0 D/SensorManager( 2064): found sensor: Analog Devices ADXL345/6 3-axis Accelerometer, handle=0
 </xterm> </xterm>
-</note>+</WRAP>
  
  
Line 122: Line 119:
 The maximum sample rate is by default limited to 200Hz, to change this limit modify define ADXL_MAX_SAMPLE_RATE_VAL in the sensor file. The maximum sample rate is by default limited to 200Hz, to change this limit modify define ADXL_MAX_SAMPLE_RATE_VAL in the sensor file.
  
-<note warning>+<WRAP alert>
 Very high sample rates > 400Hz can freeze your system! Very high sample rates > 400Hz can freeze your system!
-</note>+</WRAP>
  
-<source master/hardware/sensors/sensors_adxl34x.c:control_set_delay{} c android>+<code c
 +static int control_set_delay(struct sensors_control_context_t *dev, int32_t ms) 
 +{ 
 + int rate_val; 
 + int32_t us = ms * MSEC_TO_USEC; 
 + 
 + /* 
 + * The ADXL34x Supports 16 sample rates ranging from 3200Hz-0.098Hz 
 + * Calculate best fit and limit to max 200Hz (rate_val 11) 
 + */ 
 + 
 + for (rate_val = 0; rate_val < 16; rate_val++) 
 + if (us  >= ((10000 * MSEC_TO_USEC) >> rate_val)) 
 + break; 
 + 
 + if (rate_val > ADXL_MAX_SAMPLE_RATE_VAL) { 
 + rate_val = ADXL_MAX_SAMPLE_RATE_VAL; 
 + LOGD("Control set delay %d ms requetsed, limiting to rate %d [%d mHz]\n", 
 +      ms, rate_val, (3200000 >> (15 - rate_val))); 
 + else { 
 + LOGD("Control set delay %d ms requetsed, using rate %d [%d mHz]\n", 
 +      ms, rate_val, (3200000 >> (15 - rate_val))); 
 +
 + return write_int("rate", rate_val); 
 +
 +</code>
  
 ==== Platform data configuration ==== ==== Platform data configuration ====
Line 136: Line 158:
  
 Upon start EventHub must emit classes=0x0: Upon start EventHub must emit classes=0x0:
 +
 <code> <code>
-I/EventHub( 1862): New device: path=/dev/input/event0 name=ADXL34x accelerometer id=0x10003 (of 0x4) index=4 fd=50 classes=0x0+I/EventHub( 1862): New device: path=/dev/input/event0 name=ADXL34x  
 +accelerometer id=0x10003 (of 0x4) index=4 fd=50 classes=0x0
 </code> </code>
 classes=0x4 means that the ADXL34x driver is considered as Touchscreen. classes=0x4 means that the ADXL34x driver is considered as Touchscreen.
Line 149: Line 173:
 <code> <code>
 #echo 0 > /sys/class/input/event0/device/device/autosleep #echo 0 > /sys/class/input/event0/device/device/autosleep
 +
 </code>  </code> 
  
Line 155: Line 180:
  
 ==== The Sources ==== ==== The Sources ====
-<source master/hardware/sensors/Android.mk c android> 
  
-<source master/hardware/sensors/sensors_adxl34x.c c android>+=== Android.mk === 
 +<code c> 
 +# Copyright (C) 2008 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. 
 + 
 + 
 +LOCAL_PATH := $(call my-dir) 
 + 
 +include $(CLEAR_VARS) 
 +LOCAL_PRELINK_MODULE := false 
 +LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw 
 +LOCAL_SHARED_LIBRARIES := liblog libcutils 
 +LOCAL_SRC_FILES := sensors_adxl34x.c 
 +LOCAL_MODULE := sensors.default 
 +include $(BUILD_SHARED_LIBRARY) 
 +</code> 
 + 
 +=== sensors_adxl34x.c === 
 +<code c
 +/* 
 + * Copyright (C) 2010 Analog Devices Inc. 
 + * Copyright (C) 2008 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. 
 + */ 
 + 
 +#define LOG_TAG "sensors" 
 +#define SENSORS_SERVICE_NAME "sensors" 
 +#define ACCEL_SENSOR_NAME "ADXL34x accelerometer" 
 + 
 +#include <stdint.h> 
 +#include <string.h> 
 +#include <unistd.h> 
 +#include <errno.h> 
 +#include <fcntl.h> 
 +#include <stdlib.h> 
 +#include <stdio.h> 
 +#include <pthread.h> 
 +#include <dirent.h> 
 +#include <sys/poll.h> 
 +#include <sys/ioctl.h> 
 +#include <sys/types.h> 
 +#include <linux/input.h> 
 + 
 +#include <cutils/sockets.h> 
 +#include <cutils/properties.h> 
 +#include <cutils/atomic.h> 
 +#include <cutils/log.h> 
 +#include <cutils/native_handle.h> 
 + 
 +#include <hardware/sensors.h> 
 + 
 +/******************************************************************************/ 
 +#define ID_BASE SENSORS_HANDLE_BASE 
 +#define ID_ACCELERATION (ID_BASE + 0) 
 +#define MAX_NUM_SENSORS 1 
 +/* 
 + * This driver assumes the ADXL345/6 set in 13-bit full resolution mode +/-16g. 
 + */ 
 + 
 +#define LSG                     (256.0f) /* 3.9 mg resolution */ 
 +#define CONVERT                 (GRAVITY_EARTH / LSG) 
 +#define CONVERT_X               CONVERT 
 +#define CONVERT_Y               CONVERT 
 +#define CONVERT_Z               CONVERT 
 + 
 +#define SENSORS_ACCELERATION    (1 << ID_ACCELERATION) 
 +#define ID_A  (0) 
 +#define INPUT_DIR               "/dev/input" 
 +#define SUPPORTED_SENSORS       (SENSORS_ACCELERATION) 
 +#define EVENT_MASK_ACCEL_ALL    ((1 << ABS_X) | (1 << ABS_Y) | (1 << ABS_Z)) 
 +#define DEFAULT_THRESHOLD 100 
 + 
 +#define ACCELERATION_X (1 << ABS_X) 
 +#define ACCELERATION_Y (1 << ABS_Y) 
 +#define ACCELERATION_Z (1 << ABS_Z) 
 +#define SENSORS_ACCELERATION_ALL (ACCELERATION_X | ACCELERATION_Y | \ 
 +        ACCELERATION_Z) 
 +#define SEC_TO_NSEC 1000000000LL 
 +#define USEC_TO_NSEC 1000 
 +#define MSEC_TO_USEC 1000 
 + 
 +#define ADXL_MAX_SAMPLE_RATE_VAL 11 /* 200 Hz */ 
 + 
 +struct sensors_control_context_t { 
 + struct sensors_control_device_t device; 
 + int sensor_fd; 
 + uint32_t active_sensors; 
 +}; 
 + 
 +struct sensors_data_context_t { 
 + struct sensors_data_device_t device; 
 + int event_fd; 
 + sensors_data_t sensors[MAX_NUM_SENSORS]; 
 +}; 
 + 
 +static char input_name[20]; 
 +static char devname[PATH_MAX]; 
 + 
 +static int open_sensors_phy(struct sensors_control_device_t *dev, int keep_open) 
 +
 + char *filename; 
 + int fd; 
 + int res; 
 + uint8_t bits[4]; 
 + DIR *dir; 
 + struct dirent *de; 
 + char name[80]; 
 + 
 + dir = opendir(INPUT_DIR); 
 + if (dir == NULL) 
 + return -1; 
 + 
 + strcpy(devname, INPUT_DIR); 
 + filename = devname + strlen(devname); 
 + *filename++ = '/'; 
 + 
 + while ((de = readdir(dir))) { 
 + if (de->d_name[0] == '.' && 
 +     (de->d_name[1] == '\0' || 
 +      (de->d_name[1] == '.' && de->d_name[2] == '\0'))) 
 + continue; 
 + strcpy(filename, de->d_name); 
 + fd = open(devname, O_RDONLY); 
 + if (fd < 0) { 
 + LOGE("Couldn't open %s, error = %d", devname, fd); 
 + continue; 
 +
 + res = ioctl(fd, EVIOCGBIT(EV_ABS, 4), bits); 
 + if (res <= 0 || bits[0] != EVENT_MASK_ACCEL_ALL) { 
 + close(fd); 
 + continue; 
 +
 + 
 + if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { 
 + name[0] = '\0'; 
 +
 + 
 + if (!strcmp(name, ACCEL_SENSOR_NAME)) { 
 + strcpy(input_name, &devname[5]); 
 + LOGD("using %s (name=%s)", devname, name); 
 + } else { 
 + close(fd); 
 + continue; 
 +
 + closedir(dir); 
 + if (keep_open) { 
 + return fd; 
 + } else { 
 + close(fd); 
 + return 0; 
 +
 +
 + closedir(dir); 
 + 
 + return -1; 
 +
 + 
 +static int write_int(char const *item, int value) 
 +
 + int fd; 
 + static int already_warned = 0; 
 + char path[80]; 
 + 
 + if (input_name[0] == 0) 
 + open_sensors_phy(NULL, 0); 
 + 
 + sprintf(path, "/sys/class/%s/device/device/%s", input_name, item); 
 + 
 + fd = open(path, O_RDWR); 
 + if (fd >= 0) { 
 + char buffer[20]; 
 + int bytes = sprintf(buffer, "%d\n", value); 
 + int amt = write(fd, buffer, bytes); 
 + close(fd); 
 + return amt == -1 ? -errno : 0; 
 + } else { 
 + if (already_warned == 0) { 
 + LOGE("write_int failed to open %s\n", path); 
 + already_warned = 1; 
 +
 + return -errno; 
 +
 +
 + 
 +/* 
 + * the following is the list of all supported sensors 
 + */ 
 +static const struct sensor_t device_sensor_list[] = { 
 +
 + .name = "Analog Devices ADXL345/6 3-axis Accelerometer", 
 + .vendor = "ADI", 
 + .version = 1, 
 + .handle = ID_ACCELERATION, 
 + .type = SENSOR_TYPE_ACCELEROMETER, 
 + .maxRange = (GRAVITY_EARTH * 16.0f), 
 + .resolution = (GRAVITY_EARTH * 16.0f) / 4096.0f, 
 + .power = 0.145f, 
 + .reserved = {}, 
 + }, 
 +}; 
 + 
 +static int sensors_get_list(struct sensors_module_t *module, 
 + struct sensor_t const **list) 
 +
 + *list = device_sensor_list; 
 + return sizeof(device_sensor_list) / sizeof(device_sensor_list[0]); 
 +
 + 
 +/** Close the sensors device */ 
 +static int sensors__common_close(struct hw_device_t *dev) 
 +
 + struct sensors_data_context_t *device_data = 
 +     (struct sensors_data_context_t *)dev; 
 + 
 + if (device_data) { 
 + if (device_data->event_fd > 0) 
 + close(device_data->event_fd); 
 + 
 + free(device_data); 
 +
 + return 0; 
 +
 + 
 +static native_handle_t* control_open_data_source(struct sensors_control_device_t *dev) 
 +
 + native_handle_t* handle; 
 + int fd = open_sensors_phy(dev, 1); 
 + if (fd < 0) { 
 + return NULL; 
 +
 + 
 + handle = native_handle_create(1, 0); 
 + handle->data[0] = fd; 
 + 
 + return handle; 
 +
 + 
 +static int control_activate(struct sensors_control_context_t *dev, 
 +     int handle, int enabled) 
 +
 + uint32_t mask = (1 << handle); 
 + uint32_t sensors; 
 + uint32_t new_sensors, active, changed; 
 + int value; 
 + 
 + sensors = enabled ? mask : 0; 
 + active = dev->active_sensors; 
 + new_sensors = (active & ~mask) | (sensors & mask); 
 + changed = active ^ new_sensors; 
 + if (!changed) 
 + return 0; 
 + 
 + dev->active_sensors = new_sensors; 
 + 
 + if (enabled) { 
 + LOGD("Activate sensor\n"); 
 + value = 0; 
 + } else { 
 + LOGD("Deactivate sensor\n"); 
 + value = 1; 
 +
 + 
 + return write_int("disable", value); 
 +
 + 
 +static int control_set_delay(struct sensors_control_context_t *dev, int32_t ms) 
 +
 + int rate_val; 
 + int32_t us = ms * MSEC_TO_USEC; 
 + 
 + /* 
 + * The ADXL34x Supports 16 sample rates ranging from 3200Hz-0.098Hz 
 + * Calculate best fit and limit to max 200Hz (rate_val 11) 
 + */ 
 + 
 + for (rate_val = 0; rate_val < 16; rate_val++) 
 + if (us  >= ((10000 * MSEC_TO_USEC) >> rate_val)) 
 + break; 
 + 
 + if (rate_val > ADXL_MAX_SAMPLE_RATE_VAL) { 
 + rate_val = ADXL_MAX_SAMPLE_RATE_VAL; 
 + LOGD("Control set delay %d ms requetsed, limiting to rate %d [%d mHz]\n", 
 +      ms, rate_val, (3200000 >> (15 - rate_val))); 
 + } else { 
 + LOGD("Control set delay %d ms requetsed, using rate %d [%d mHz]\n", 
 +      ms, rate_val, (3200000 >> (15 - rate_val))); 
 +
 + return write_int("rate", rate_val); 
 +
 + 
 +static int control_wake(struct sensors_control_context_t *dev) 
 +
 + int err = 0; 
 + int fd = open(devname, O_WRONLY); 
 + if (fd > 0) { 
 + struct input_event event[1]; 
 + event[0].type = EV_SYN; 
 + event[0].code = SYN_CONFIG; 
 + event[0].value = 0; 
 + err = write(fd, event, sizeof(event)); 
 + LOGD_IF(err < 0, "control__wake, err=%d (%s)", errno, strerror(errno)); 
 + close(fd); 
 +
 + return err; 
 +
 + 
 +static int control_close(struct hw_device_t *dev) 
 +
 + struct sensors_control_context_t *device_control = (void *)dev; 
 + 
 + if (device_control) { 
 + if (device_control->sensor_fd > 0) 
 + close(device_control->sensor_fd); 
 + free(device_control); 
 +
 + 
 + return 0; 
 +
 + 
 +static int sensors__data_open(struct sensors_data_context_t *dev, native_handle_t* handle) 
 +
 + int i; 
 + memset(&dev->sensors, 0, sizeof(dev->sensors)); 
 + 
 + for (i = 0; i < MAX_NUM_SENSORS; i++) { 
 + dev->sensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH; 
 +
 + dev->event_fd = dup(handle->data[0]); 
 + /* native_handle_close(handle); */ 
 + native_handle_delete(handle); 
 + return 0; 
 + 
 +
 + 
 +static int sensors__data_close(struct sensors_data_device_t *dev) 
 +
 + struct sensors_data_context_t *data_device = 
 +     (struct sensors_data_context_t *)dev; 
 + 
 + if (data_device->event_fd > 0) { 
 + close(data_device->event_fd); 
 +
 + 
 + return 0; 
 +
 + 
 +static int sensors__data_poll(struct sensors_data_context_t *dev, sensors_data_t * values) 
 +
 + struct input_event ev; 
 + int ret; 
 + uint32_t new_sensors = 0; 
 + int fd = dev->event_fd; 
 + 
 + while (1) { 
 + ret = read(fd, &ev, sizeof(ev)); 
 + 
 + if (ret < (int)sizeof(ev)) 
 + break; 
 + 
 + if (ev.type == EV_ABS) { 
 + /* Orientation or acceleration event */ 
 + switch (ev.code) { 
 + case ABS_X: 
 + new_sensors |= ACCELERATION_X; 
 + dev->sensors[ID_A].acceleration.x = ev.value * CONVERT_X; 
 + break; 
 + case ABS_Y: 
 + new_sensors |= ACCELERATION_Y; 
 + dev->sensors[ID_A].acceleration.y = ev.value * CONVERT_Y; 
 + break; 
 + case ABS_Z: 
 + new_sensors |= ACCELERATION_Z; 
 + dev->sensors[ID_A].acceleration.z = ev.value * CONVERT_Z; 
 + break; 
 +
 + } else if (ev.type == EV_SYN) { 
 + 
 + if (ev.code == SYN_CONFIG) { 
 + /* Injected event by control_wake 
 + * return immediately 
 + */ 
 + return 0x7FFFFFFF; 
 +
 + 
 + /* 
 + * Linux Input suppresses identical events, so if 
 + * only ABS_Z changes and ABS_X,Y stays constant 
 + * between events we need to report the cached values. 
 + * Many other drivers start to scramble events by 
 + * waiting for a full triplet to arrive. 
 + * Other events on the ADXL345/6 such as TAP 
 + * should be turned off. 
 + */ 
 + if (new_sensors) { 
 + int64_t t = 
 +     ev.time.tv_sec * SEC_TO_NSEC + 
 +     ev.time.tv_usec * USEC_TO_NSEC; 
 + new_sensors = 0; 
 + 
 + dev->sensors[ID_A].time = t; 
 + *values = dev->sensors[ID_A]; 
 + values->sensor = ID_ACCELERATION; 
 + return ID_ACCELERATION; 
 +
 +
 +
 + return 0; 
 +
 + 
 +/******************************************************************************/ 
 + 
 +/** 
 + * module methods 
 + */ 
 + 
 +/** Open a new instance of a sensor device using name */ 
 +static int open_sensors(const struct hw_module_t *module, const char *name, 
 + struct hw_device_t **device) 
 +
 + int status = -EINVAL; 
 + if (!strcmp(name, SENSORS_HARDWARE_CONTROL)) { 
 + struct sensors_control_context_t *dev; 
 + dev = malloc(sizeof(*dev)); 
 + memset(dev, 0, sizeof(*dev)); 
 + dev->sensor_fd = -1; 
 + dev->device.common.tag = HARDWARE_DEVICE_TAG; 
 + dev->device.common.version = 0; 
 + dev->device.common.module = (struct hw_module_t *)module; 
 + dev->device.common.close = control_close; 
 + dev->device.open_data_source = control_open_data_source; 
 + dev->device.activate = control_activate; 
 + dev->device.set_delay = control_set_delay; 
 + dev->device.wake = control_wake; 
 + *device = &dev->device.common; 
 + } else if (!strcmp(name, SENSORS_HARDWARE_DATA)) { 
 + struct sensors_data_context_t *dev; 
 + dev = malloc(sizeof(*dev)); 
 + memset(dev, 0, sizeof(*dev)); 
 + dev->event_fd = -1; 
 + dev->device.common.tag = HARDWARE_DEVICE_TAG; 
 + dev->device.common.version = 0; 
 + dev->device.common.module = (struct hw_module_t *)module; 
 + dev->device.common.close = sensors__common_close; 
 + dev->device.data_open = sensors__data_open; 
 + dev->device.data_close = sensors__data_close; 
 + dev->device.poll = sensors__data_poll; 
 + *device = &dev->device.common; 
 +
 + return status; 
 +
 + 
 +static struct hw_module_methods_t sensors_module_methods = { 
 + .open = open_sensors, 
 +}; 
 + 
 +/* 
 + * The Sensors Hardware Module 
 + */ 
 +const struct sensors_module_t HAL_MODULE_INFO_SYM = { 
 + .common = { 
 +    .tag = HARDWARE_MODULE_TAG, 
 +    .version_major = 1, 
 +    .version_minor = 0, 
 +    .id = SENSORS_HARDWARE_MODULE_ID, 
 +    .name = "Analog Devices ADXL345/6 sensor", 
 +    .author = "OPS MH", 
 +    .methods = &sensors_module_methods, 
 +    }, 
 + .get_sensors_list = sensors_get_list, 
 +}; 
 + 
 +</code>
resources/tools-software/android-drivers/sensor-acceleration/adxl345.txt · Last modified: 11 Dec 2013 09:57 by Michael Hennerich