diff options
Diffstat (limited to 'sensors/sensors_trout.c')
-rw-r--r-- | sensors/sensors_trout.c | 599 |
1 files changed, 0 insertions, 599 deletions
diff --git a/sensors/sensors_trout.c b/sensors/sensors_trout.c deleted file mode 100644 index f3c0b3a..0000000 --- a/sensors/sensors_trout.c +++ /dev/null @@ -1,599 +0,0 @@ -/* - * Copyright 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" - -#include <hardware/sensors.h> -#include <fcntl.h> -#include <errno.h> -#include <dirent.h> -#include <math.h> -#include <poll.h> - -#include <linux/input.h> -#include <linux/akm8976.h> - -#include <cutils/log.h> -#include <cutils/atomic.h> - -/*****************************************************************************/ - -#define AKM_DEVICE_NAME "/dev/akm8976_aot" - -#define SUPPORTED_SENSORS (SENSORS_ORIENTATION | \ - SENSORS_ACCELERATION | \ - SENSORS_MAGNETIC_FIELD | \ - SENSORS_ORIENTATION_RAW) - - -// sensor IDs must be a power of two and -// must match values in SensorManager.java -#define EVENT_TYPE_ACCEL_X ABS_X -#define EVENT_TYPE_ACCEL_Y ABS_Z -#define EVENT_TYPE_ACCEL_Z ABS_Y -#define EVENT_TYPE_ACCEL_STATUS ABS_WHEEL - -#define EVENT_TYPE_YAW ABS_RX -#define EVENT_TYPE_PITCH ABS_RY -#define EVENT_TYPE_ROLL ABS_RZ -#define EVENT_TYPE_ORIENT_STATUS ABS_RUDDER - -#define EVENT_TYPE_MAGV_X ABS_HAT0X -#define EVENT_TYPE_MAGV_Y ABS_HAT0Y -#define EVENT_TYPE_MAGV_Z ABS_BRAKE - -#define EVENT_TYPE_TEMPERATURE ABS_THROTTLE -#define EVENT_TYPE_STEP_COUNT ABS_GAS - -// 720 LSG = 1G -#define LSG (720.0f) - -// conversion of acceleration data to SI units (m/s^2) -#define CONVERT_A (GRAVITY_EARTH / LSG) -#define CONVERT_A_X (CONVERT_A) -#define CONVERT_A_Y (-CONVERT_A) -#define CONVERT_A_Z (CONVERT_A) - -// conversion of magnetic data to uT units -#define CONVERT_M (1.0f/16.0f) -#define CONVERT_M_X (CONVERT_M) -#define CONVERT_M_Y (CONVERT_M) -#define CONVERT_M_Z (CONVERT_M) - -#define SENSOR_STATE_MASK (0x7FFF) - -/*****************************************************************************/ - -static int sAkmFD = -1; -static uint32_t sActiveSensors = 0; - -/*****************************************************************************/ - -/* - * We use a Least Mean Squares filter to smooth out the output of the yaw - * sensor. - * - * The goal is to estimate the output of the sensor based on previous acquired - * samples. - * - * We approximate the input by a line with the equation: - * Z(t) = a * t + b - * - * We use the Least Mean Squares method to calculate a and b so that the - * distance between the line and the measured COUNT inputs Z(t) is minimal. - * - * In practice we only need to compute b, which is the value we're looking for - * (it's the estimated Z at t=0). However, to improve the latency a little bit, - * we're going to discard a certain number of samples that are too far from - * the estimated line and compute b again with the new (trimmed down) samples. - * - * notes: - * 'a' is the slope of the line, and physicaly represent how fast the input - * is changing. In our case, how fast the yaw is changing, that is, how fast the - * user is spinning the device (in degre / nanosecond). This value should be - * zero when the device is not moving. - * - * The minimum distance between the line and the samples (which we are not - * explicitely computing here), is an indication of how bad the samples are - * and gives an idea of the "quality" of the estimation (well, really of the - * sensor values). - * - */ - -/* sensor rate in me */ -#define SENSORS_RATE_MS 20 -/* timeout (constant value) in ms */ -#define SENSORS_TIMEOUT_MS 100 -/* # of samples to look at in the past for filtering */ -#define COUNT 24 -/* prediction ratio */ -#define PREDICTION_RATIO (1.0f/3.0f) -/* prediction time in seconds (>=0) */ -#define PREDICTION_TIME ((SENSORS_RATE_MS*COUNT/1000.0f)*PREDICTION_RATIO) - -static float mV[COUNT*2]; -static float mT[COUNT*2]; -static int mIndex; - -static inline -float normalize(float x) -{ - x *= (1.0f / 360.0f); - if (fabsf(x) >= 0.5f) - x = x - ceilf(x + 0.5f) + 1.0f; - if (x < 0) - x += 1.0f; - x *= 360.0f; - return x; -} - -static void LMSInit(void) -{ - memset(mV, 0, sizeof(mV)); - memset(mT, 0, sizeof(mT)); - mIndex = COUNT; -} - -static float LMSFilter(int64_t time, int v) -{ - const float ns = 1.0f / 1000000000.0f; - const float t = time*ns; - float v1 = mV[mIndex]; - if ((v-v1) > 180) { - v -= 360; - } else if ((v1-v) > 180) { - v += 360; - } - /* Manage the circular buffer, we write the data twice spaced by COUNT - * values, so that we don't have to memcpy() the array when it's full */ - mIndex++; - if (mIndex >= COUNT*2) - mIndex = COUNT; - mV[mIndex] = v; - mT[mIndex] = t; - mV[mIndex-COUNT] = v; - mT[mIndex-COUNT] = t; - - float A, B, C, D, E; - float a, b; - int i; - - A = B = C = D = E = 0; - for (i=0 ; i<COUNT-1 ; i++) { - const int j = mIndex - 1 - i; - const float Z = mV[j]; - const float T = 0.5f*(mT[j] + mT[j+1]) - t; - float dT = mT[j] - mT[j+1]; - dT *= dT; - A += Z*dT; - B += T*(T*dT); - C += (T*dT); - D += Z*(T*dT); - E += dT; - } - b = (A*B + C*D) / (E*B + C*C); - a = (E*b - A) / C; - float f = b + PREDICTION_TIME*a; - - //LOGD("A=%f, B=%f, C=%f, D=%f, E=%f", A,B,C,D,E); - //LOGD("%lld %d %f %f", time, v, f, a); - - f = normalize(f); - return f; -} - -/*****************************************************************************/ - -static int open_input() -{ - /* scan all input drivers and look for "compass" */ - int fd = -1; - const char *dirname = "/dev/input"; - char devname[PATH_MAX]; - char *filename; - DIR *dir; - struct dirent *de; - dir = opendir(dirname); - if(dir == NULL) - return -1; - strcpy(devname, dirname); - 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) { - char name[80]; - if (ioctl(fd, EVIOCGNAME(sizeof(name) - 1), &name) < 1) { - name[0] = '\0'; - } - if (!strcmp(name, "compass")) { - LOGD("using %s (name=%s)", devname, name); - break; - } - close(fd); - fd = -1; - } - } - closedir(dir); - - if (fd < 0) { - LOGE("Couldn't find or open 'compass' driver (%s)", strerror(errno)); - } - return fd; -} - -static int open_akm() -{ - if (sAkmFD <= 0) { - sAkmFD = open(AKM_DEVICE_NAME, O_RDONLY); - LOGD("%s, fd=%d", __PRETTY_FUNCTION__, sAkmFD); - LOGE_IF(sAkmFD<0, "Couldn't open %s (%s)", - AKM_DEVICE_NAME, strerror(errno)); - if (sAkmFD >= 0) { - sActiveSensors = 0; - } - } - return sAkmFD; -} - -static void close_akm() -{ - if (sAkmFD > 0) { - LOGD("%s, fd=%d", __PRETTY_FUNCTION__, sAkmFD); - close(sAkmFD); - sAkmFD = -1; - } -} - -static void enable_disable(int fd, uint32_t sensors, uint32_t mask) -{ - if (fd<0) return; - short flags; - - if (sensors & SENSORS_ORIENTATION_RAW) { - sensors |= SENSORS_ORIENTATION; - mask |= SENSORS_ORIENTATION; - } else if (mask & SENSORS_ORIENTATION_RAW) { - mask |= SENSORS_ORIENTATION; - } - - if (mask & SENSORS_ORIENTATION) { - flags = (sensors & SENSORS_ORIENTATION) ? 1 : 0; - if (ioctl(fd, ECS_IOCTL_APP_SET_MFLAG, &flags) < 0) { - LOGE("ECS_IOCTL_APP_SET_MFLAG error (%s)", strerror(errno)); - } - } - if (mask & SENSORS_ACCELERATION) { - flags = (sensors & SENSORS_ACCELERATION) ? 1 : 0; - if (ioctl(fd, ECS_IOCTL_APP_SET_AFLAG, &flags) < 0) { - LOGE("ECS_IOCTL_APP_SET_AFLAG error (%s)", strerror(errno)); - } - } - if (mask & SENSORS_TEMPERATURE) { - flags = (sensors & SENSORS_TEMPERATURE) ? 1 : 0; - if (ioctl(fd, ECS_IOCTL_APP_SET_TFLAG, &flags) < 0) { - LOGE("ECS_IOCTL_APP_SET_TFLAG error (%s)", strerror(errno)); - } - } -#ifdef ECS_IOCTL_APP_SET_MVFLAG - if (mask & SENSORS_MAGNETIC_FIELD) { - flags = (sensors & SENSORS_MAGNETIC_FIELD) ? 1 : 0; - if (ioctl(fd, ECS_IOCTL_APP_SET_MVFLAG, &flags) < 0) { - LOGE("ECS_IOCTL_APP_SET_MVFLAG error (%s)", strerror(errno)); - } - } -#endif -} - -static uint32_t read_sensors_state(int fd) -{ - if (fd<0) return 0; - short flags; - uint32_t sensors = 0; - // read the actual value of all sensors - if (!ioctl(fd, ECS_IOCTL_APP_GET_MFLAG, &flags)) { - if (flags) sensors |= SENSORS_ORIENTATION; - else sensors &= ~SENSORS_ORIENTATION; - } - if (!ioctl(fd, ECS_IOCTL_APP_GET_AFLAG, &flags)) { - if (flags) sensors |= SENSORS_ACCELERATION; - else sensors &= ~SENSORS_ACCELERATION; - } - if (!ioctl(fd, ECS_IOCTL_APP_GET_TFLAG, &flags)) { - if (flags) sensors |= SENSORS_TEMPERATURE; - else sensors &= ~SENSORS_TEMPERATURE; - } -#ifdef ECS_IOCTL_APP_SET_MVFLAG - if (!ioctl(fd, ECS_IOCTL_APP_GET_MVFLAG, &flags)) { - if (flags) sensors |= SENSORS_MAGNETIC_FIELD; - else sensors &= ~SENSORS_MAGNETIC_FIELD; - } -#endif - return sensors; -} - -/*****************************************************************************/ - -uint32_t sensors_control_init() -{ - return SUPPORTED_SENSORS; -} - -int sensors_control_open() -{ - return open_input(); -} - -uint32_t sensors_control_activate(uint32_t sensors, uint32_t mask) -{ - mask &= SUPPORTED_SENSORS; - uint32_t active = sActiveSensors; - uint32_t new_sensors = (active & ~mask) | (sensors & mask); - uint32_t changed = active ^ new_sensors; - if (changed) { - int fd = open_akm(); - if (fd < 0) return 0; - - if (!active && new_sensors) { - // force all sensors to be updated - changed = SUPPORTED_SENSORS; - } - - enable_disable(fd, new_sensors, changed); - - if (active && !new_sensors) { - // close the driver - close_akm(); - } - sActiveSensors = active = new_sensors; - LOGD("sensors=%08x, real=%08x", - sActiveSensors, read_sensors_state(fd)); - } - return active; -} - -int sensors_control_delay(int32_t ms) -{ -#ifdef ECS_IOCTL_APP_SET_DELAY - if (sAkmFD <= 0) { - return -1; - } - short delay = ms; - if (!ioctl(sAkmFD, ECS_IOCTL_APP_SET_DELAY, &delay)) { - return -errno; - } - return 0; -#else - return -1; -#endif -} - -/*****************************************************************************/ - -#define MAX_NUM_SENSORS 8 -static int sInputFD = -1; -static const int ID_O = 0; -static const int ID_A = 1; -static const int ID_T = 2; -static const int ID_M = 3; -static const int ID_OR = 7; // orientation raw -static sensors_data_t sSensors[MAX_NUM_SENSORS]; -static uint32_t sPendingSensors; - -int sensors_data_open(int fd) -{ - int i; - LMSInit(); - memset(&sSensors, 0, sizeof(sSensors)); - for (i=0 ; i<MAX_NUM_SENSORS ; i++) { - // by default all sensors have high accuracy - // (we do this because we don't get an update if the value doesn't - // change). - sSensors[i].vector.status = SENSOR_STATUS_ACCURACY_HIGH; - } - sPendingSensors = 0; - sInputFD = dup(fd); - LOGD("sensors_data_open: fd = %d", sInputFD); - return 0; -} - -int sensors_data_close() -{ - close(sInputFD); - sInputFD = -1; - return 0; -} - -static int pick_sensor(sensors_data_t* values) -{ - uint32_t mask = SENSORS_MASK; - while(mask) { - uint32_t i = 31 - __builtin_clz(mask); - mask &= ~(1<<i); - if (sPendingSensors & (1<<i)) { - sPendingSensors &= ~(1<<i); - *values = sSensors[i]; - values->sensor = (1<<i); - LOGD_IF(0, "%d [%f, %f, %f]", (1<<i), - values->vector.x, - values->vector.y, - values->vector.z); - return (1<<i); - } - } - LOGE("No sensor to return!!! sPendingSensors=%08x", sPendingSensors); - // we may end-up in a busy loop, slow things down, just in case. - usleep(100000); - return -1; -} - -int sensors_data_poll(sensors_data_t* values, uint32_t sensors_of_interest) -{ - struct input_event event; - int nread; - int64_t t; - - int fd = sInputFD; - if (fd <= 0) - return -1; - - // there are pending sensors, returns them now... - if (sPendingSensors) { - return pick_sensor(values); - } - - uint32_t new_sensors = 0; - struct pollfd fds; - fds.fd = fd; - fds.events = POLLIN; - fds.revents = 0; - - // wait until we get a complete event for an enabled sensor - while (1) { - nread = 0; - if (sensors_of_interest & SENSORS_ORIENTATION) { - /* We do some special processing if the orientation sensor is - * activated. In particular the yaw value is filtered with a - * LMS filter. Since the kernel only sends an event when the - * value changes, we need to wake up at regular intervals to - * generate an output value (the output value may not be - * constant when the input value is constant) - */ - int err = poll(&fds, 1, SENSORS_TIMEOUT_MS); - if (err == 0) { - struct timespec time; - time.tv_sec = time.tv_nsec = 0; - clock_gettime(CLOCK_MONOTONIC, &time); - - /* generate an output value */ - t = time.tv_sec*1000000000LL+time.tv_nsec; - new_sensors |= SENSORS_ORIENTATION; - sSensors[ID_O].orientation.yaw = - LMSFilter(t, sSensors[ID_O].orientation.yaw); - - /* generate a fake sensors event */ - event.type = EV_SYN; - event.time.tv_sec = time.tv_sec; - event.time.tv_usec = time.tv_nsec/1000; - nread = sizeof(event); - } - } - if (nread == 0) { - /* read the next event */ - nread = read(fd, &event, sizeof(event)); - } - if (nread == sizeof(event)) { - uint32_t v; - if (event.type == EV_ABS) { - //LOGD("type: %d code: %d value: %-5d time: %ds", - // event.type, event.code, event.value, - // (int)event.time.tv_sec); - switch (event.code) { - - case EVENT_TYPE_ACCEL_X: - new_sensors |= SENSORS_ACCELERATION; - sSensors[ID_A].acceleration.x = event.value * CONVERT_A_X; - break; - case EVENT_TYPE_ACCEL_Y: - new_sensors |= SENSORS_ACCELERATION; - sSensors[ID_A].acceleration.y = event.value * CONVERT_A_Y; - break; - case EVENT_TYPE_ACCEL_Z: - new_sensors |= SENSORS_ACCELERATION; - sSensors[ID_A].acceleration.z = event.value * CONVERT_A_Z; - break; - - case EVENT_TYPE_MAGV_X: - new_sensors |= SENSORS_MAGNETIC_FIELD; - sSensors[ID_M].magnetic.x = event.value * CONVERT_M_X; - break; - case EVENT_TYPE_MAGV_Y: - new_sensors |= SENSORS_MAGNETIC_FIELD; - sSensors[ID_M].magnetic.y = event.value * CONVERT_M_Y; - break; - case EVENT_TYPE_MAGV_Z: - new_sensors |= SENSORS_MAGNETIC_FIELD; - sSensors[ID_M].magnetic.z = event.value * CONVERT_M_Z; - break; - - case EVENT_TYPE_YAW: - new_sensors |= SENSORS_ORIENTATION | SENSORS_ORIENTATION_RAW; - t = event.time.tv_sec*1000000000LL + - event.time.tv_usec*1000; - sSensors[ID_O].orientation.yaw = - (sensors_of_interest & SENSORS_ORIENTATION) ? - LMSFilter(t, event.value) : event.value; - sSensors[ID_OR].orientation.yaw = event.value; - break; - case EVENT_TYPE_PITCH: - new_sensors |= SENSORS_ORIENTATION | SENSORS_ORIENTATION_RAW; - sSensors[ID_O].orientation.pitch = event.value; - sSensors[ID_OR].orientation.pitch = event.value; - break; - case EVENT_TYPE_ROLL: - new_sensors |= SENSORS_ORIENTATION | SENSORS_ORIENTATION_RAW; - sSensors[ID_O].orientation.roll = event.value; - sSensors[ID_OR].orientation.roll = event.value; - break; - - case EVENT_TYPE_TEMPERATURE: - new_sensors |= SENSORS_TEMPERATURE; - sSensors[ID_T].temperature = event.value; - break; - - case EVENT_TYPE_STEP_COUNT: - // step count (only reported in MODE_FFD) - // we do nothing with it for now. - break; - case EVENT_TYPE_ACCEL_STATUS: - // accuracy of the calibration (never returned!) - //LOGD("G-Sensor status %d", event.value); - break; - case EVENT_TYPE_ORIENT_STATUS: - // accuracy of the calibration - v = (uint32_t)(event.value & SENSOR_STATE_MASK); - LOGD_IF(sSensors[ID_O].orientation.status != (uint8_t)v, - "M-Sensor status %d", v); - sSensors[ID_O].orientation.status = (uint8_t)v; - sSensors[ID_OR].orientation.status = (uint8_t)v; - break; - } - } else if (event.type == EV_SYN) { - if (new_sensors) { - sPendingSensors = new_sensors; - int64_t t = event.time.tv_sec*1000000000LL + - event.time.tv_usec*1000; - while (new_sensors) { - uint32_t i = 31 - __builtin_clz(new_sensors); - new_sensors &= ~(1<<i); - sSensors[i].time = t; - } - return pick_sensor(values); - } - } - } - } -} - -uint32_t sensors_data_get_sensors() { - return SUPPORTED_SENSORS; -} - |