summaryrefslogtreecommitdiffstats
path: root/sensors/akmdfs
diff options
context:
space:
mode:
Diffstat (limited to 'sensors/akmdfs')
-rw-r--r--sensors/akmdfs/AK8975Driver.c318
-rw-r--r--sensors/akmdfs/AK8975Driver.h102
-rw-r--r--sensors/akmdfs/AKFS_APIs.c389
-rw-r--r--sensors/akmdfs/AKFS_APIs.h69
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.c44
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.h50
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.c333
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.h53
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_Configure.h37
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.c110
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.h107
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.c133
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.h39
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_Math.h47
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.c107
-rw-r--r--sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.h46
-rw-r--r--sensors/akmdfs/AKFS_CSpec.h38
-rw-r--r--sensors/akmdfs/AKFS_Common.h141
-rw-r--r--sensors/akmdfs/AKFS_Compass.h84
-rw-r--r--sensors/akmdfs/AKFS_Disp.c89
-rw-r--r--sensors/akmdfs/AKFS_Disp.h52
-rw-r--r--sensors/akmdfs/AKFS_FileIO.c130
-rw-r--r--sensors/akmdfs/AKFS_FileIO.h39
-rw-r--r--sensors/akmdfs/AKFS_Measure.c410
-rw-r--r--sensors/akmdfs/AKFS_Measure.h70
-rw-r--r--sensors/akmdfs/NOTICE202
-rw-r--r--sensors/akmdfs/Version.txt31
-rw-r--r--sensors/akmdfs/main.c293
28 files changed, 3563 insertions, 0 deletions
diff --git a/sensors/akmdfs/AK8975Driver.c b/sensors/akmdfs/AK8975Driver.c
new file mode 100644
index 0000000..003c8d2
--- /dev/null
+++ b/sensors/akmdfs/AK8975Driver.c
@@ -0,0 +1,318 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include <fcntl.h>
+#include "AKFS_Common.h"
+#include "AK8975Driver.h"
+
+#define MSENSOR_NAME "/dev/akm8975_dev"
+
+static int s_fdDev = -1;
+
+/*!
+ Open device driver.
+ This function opens both device drivers of magnetic sensor and acceleration
+ sensor. Additionally, some initial hardware settings are done, such as
+ measurement range, built-in filter function and etc.
+ @return If this function succeeds, the return value is #AKD_SUCCESS.
+ Otherwise the return value is #AKD_FAIL.
+ */
+int16_t AKD_InitDevice(void)
+{
+ if (s_fdDev < 0) {
+ /* Open magnetic sensor's device driver. */
+ if ((s_fdDev = open(MSENSOR_NAME, O_RDWR)) < 0) {
+ AKMERROR_STR("open");
+ return AKD_FAIL;
+ }
+ }
+
+ return AKD_SUCCESS;
+}
+
+/*!
+ Close device driver.
+ This function closes both device drivers of magnetic sensor and acceleration
+ sensor.
+ */
+void AKD_DeinitDevice(void)
+{
+ if (s_fdDev >= 0) {
+ close(s_fdDev);
+ s_fdDev = -1;
+ }
+}
+
+/*!
+ Writes data to a register of the AK8975. When more than one byte of data is
+ specified, the data is written in contiguous locations starting at an address
+ specified in \a address.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[in] address Specify the address of a register in which data is to be
+ written.
+ @param[in] data Specify data to write or a pointer to a data array containing
+ the data. When specifying more than one byte of data, specify the starting
+ address of the array.
+ @param[in] numberOfBytesToWrite Specify the number of bytes that make up the
+ data to write. When a pointer to an array is specified in data, this argument
+ equals the number of elements of the array.
+ */
+int16_t AKD_TxData(
+ const BYTE address,
+ const BYTE * data,
+ const uint16_t numberOfBytesToWrite)
+{
+ int i;
+ char buf[RWBUF_SIZE];
+
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+ if (numberOfBytesToWrite > (RWBUF_SIZE-2)) {
+ ALOGE("%s: Tx size is too large.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+
+ buf[0] = numberOfBytesToWrite + 1;
+ buf[1] = address;
+
+ for (i = 0; i < numberOfBytesToWrite; i++) {
+ buf[i + 2] = data[i];
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_WRITE, buf) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ } else {
+
+#if ENABLE_AKMDEBUG
+ AKMDATA(AKMDATA_DRV, "addr(HEX)=%02x data(HEX)=", address);
+ for (i = 0; i < numberOfBytesToWrite; i++) {
+ AKMDATA(AKMDATA_DRV, " %02x", data[i]);
+ }
+ AKMDATA(AKMDATA_DRV, "\n");
+#endif
+ return AKD_SUCCESS;
+ }
+}
+
+/*!
+ Acquires data from a register or the EEPROM of the AK8975.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[in] address Specify the address of a register from which data is to be
+ read.
+ @param[out] data Specify a pointer to a data array which the read data are
+ stored.
+ @param[in] numberOfBytesToRead Specify the number of bytes that make up the
+ data to read. When a pointer to an array is specified in data, this argument
+ equals the number of elements of the array.
+ */
+int16_t AKD_RxData(
+ const BYTE address,
+ BYTE * data,
+ const uint16_t numberOfBytesToRead)
+{
+ int i;
+ char buf[RWBUF_SIZE];
+
+ memset(data, 0, numberOfBytesToRead);
+
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+ if (numberOfBytesToRead > (RWBUF_SIZE-1)) {
+ ALOGE("%s: Rx size is too large.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+
+ buf[0] = numberOfBytesToRead;
+ buf[1] = address;
+
+ if (ioctl(s_fdDev, ECS_IOCTL_READ, buf) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ } else {
+ for (i = 0; i < numberOfBytesToRead; i++) {
+ data[i] = buf[i + 1];
+ }
+#if ENABLE_AKMDEBUG
+ AKMDATA(AKMDATA_DRV, "addr(HEX)=%02x len=%d data(HEX)=",
+ address, numberOfBytesToRead);
+ for (i = 0; i < numberOfBytesToRead; i++) {
+ AKMDATA(AKMDATA_DRV, " %02x", data[i]);
+ }
+ AKMDATA(AKMDATA_DRV, "\n");
+#endif
+ return AKD_SUCCESS;
+ }
+}
+
+/*!
+ Acquire magnetic data from AK8975. If measurement is not done, this function
+ waits until measurement completion.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] data A magnetic data array. The size should be larger than #SENSOR_DATA_SIZE.
+ */
+int16_t AKD_GetMagneticData(BYTE data[SENSOR_DATA_SIZE])
+{
+ memset(data, 0, SENSOR_DATA_SIZE);
+
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+
+ if (ioctl(s_fdDev, ECS_IOCTL_GETDATA, data) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+
+ AKMDATA(AKMDATA_DRV,
+ "bdata(HEX)= %02x %02x %02x %02x %02x %02x %02x %02x\n",
+ data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]);
+
+ return AKD_SUCCESS;
+}
+
+/*!
+ Set calculated data to device driver.
+ @param[in] buf The order of input data depends on driver's specification.
+ */
+void AKD_SetYPR(const int buf[YPR_DATA_SIZE])
+{
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ } else {
+ if (ioctl(s_fdDev, ECS_IOCTL_SET_YPR, buf) < 0) {
+ AKMERROR_STR("ioctl");
+ }
+ }
+}
+
+/*!
+ */
+int AKD_GetOpenStatus(int* status)
+{
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_OPEN_STATUS, status) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ */
+int AKD_GetCloseStatus(int* status)
+{
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_CLOSE_STATUS, status) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ Set AK8975 to the specific mode.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[in] mode This value should be one of the AK8975_Mode which is defined in
+ akm8975.h file.
+ */
+int16_t AKD_SetMode(const BYTE mode)
+{
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+
+ if (ioctl(s_fdDev, ECS_IOCTL_SET_MODE, &mode) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+
+ return AKD_SUCCESS;
+}
+
+/*!
+ Acquire delay
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] delay A delay in nanosecond.
+ */
+int16_t AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS])
+{
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.\n", __FUNCTION__);
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_DELAY, delay) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+ return AKD_SUCCESS;
+}
+
+/*!
+ Get layout information from device driver, i.e. platform data.
+ */
+int16_t AKD_GetLayout(int16_t* layout)
+{
+ char tmp;
+
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_LAYOUT, &tmp) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+
+ *layout = tmp;
+ return AKD_SUCCESS;
+}
+
+/* Get acceleration data. */
+int16_t AKD_GetAccelerationData(int16_t data[3])
+{
+ if (s_fdDev < 0) {
+ ALOGE("%s: Device file is not opened.", __FUNCTION__);
+ return AKD_FAIL;
+ }
+ if (ioctl(s_fdDev, ECS_IOCTL_GET_ACCEL, data) < 0) {
+ AKMERROR_STR("ioctl");
+ return AKD_FAIL;
+ }
+
+ AKMDATA(AKMDATA_DRV, "%s: acc=%d, %d, %d\n",
+ __FUNCTION__, data[0], data[1], data[2]);
+
+ return AKD_SUCCESS;
+}
diff --git a/sensors/akmdfs/AK8975Driver.h b/sensors/akmdfs/AK8975Driver.h
new file mode 100644
index 0000000..731210d
--- /dev/null
+++ b/sensors/akmdfs/AK8975Driver.h
@@ -0,0 +1,102 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKMD_INC_AK8975DRIVER_H
+#define AKMD_INC_AK8975DRIVER_H
+
+#include <linux/akm8975.h> /* Device driver */
+#include <stdint.h> /* int8_t, int16_t etc. */
+
+/*** Constant definition ******************************************************/
+#define AKD_TRUE 1 /*!< Represents true */
+#define AKD_FALSE 0 /*!< Represents false */
+#define AKD_SUCCESS 1 /*!< Represents success.*/
+#define AKD_FAIL 0 /*!< Represents fail. */
+#define AKD_ERROR -1 /*!< Represents error. */
+
+/*! 0:Don't Output data, 1:Output data */
+#define AKD_DBG_DATA 0
+/*! Typical interval in ns */
+#define AK8975_MEASUREMENT_TIME_NS ((AK8975_MEASUREMENT_TIME_US) * 1000)
+/*! 720 LSG = 1G = 9.8 m/s2 */
+#define LSG 720
+
+
+/*** Type declaration *********************************************************/
+typedef unsigned char BYTE;
+
+/*!
+ Open device driver.
+ This function opens device driver of acceleration sensor.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ */
+typedef int16_t(*ACCFNC_INITDEVICE)(void);
+
+/*!
+ Close device driver.
+ This function closes device drivers of acceleration sensor.
+ */
+typedef void(*ACCFNC_DEINITDEVICE)(void);
+
+/*!
+ Acquire acceleration data from acceleration sensor and convert it to Android
+ coordinate system.
+ @return If this function succeeds, the return value is #AKD_SUCCESS. Otherwise
+ the return value is #AKD_FAIL.
+ @param[out] data A acceleration data array. The coordinate system of the
+ acquired data follows the definition of Android. Unit is SmartCompass.
+ */
+typedef int16_t(*ACCFNC_GETACCDATA)(short data[3]);
+
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of Function ***************************************************/
+
+int16_t AKD_InitDevice(void);
+
+void AKD_DeinitDevice(void);
+
+int16_t AKD_TxData(
+ const BYTE address,
+ const BYTE* data,
+ const uint16_t numberOfBytesToWrite);
+
+int16_t AKD_RxData(
+ const BYTE address,
+ BYTE* data,
+ const uint16_t numberOfBytesToRead);
+
+int16_t AKD_GetMagneticData(BYTE data[SENSOR_DATA_SIZE]);
+
+void AKD_SetYPR(const int buf[YPR_DATA_SIZE]);
+
+int AKD_GetOpenStatus(int* status);
+
+int AKD_GetCloseStatus(int* status);
+
+int16_t AKD_SetMode(const BYTE mode);
+
+int16_t AKD_GetDelay(int64_t delay[AKM_NUM_SENSORS]);
+
+int16_t AKD_GetLayout(int16_t* layout);
+
+int16_t AKD_GetAccelerationData(int16_t data[3]);
+
+#endif /* AKMD_INC_AK8975DRIVER_H */
+
diff --git a/sensors/akmdfs/AKFS_APIs.c b/sensors/akmdfs/AKFS_APIs.c
new file mode 100644
index 0000000..ace9bc1
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs.c
@@ -0,0 +1,389 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_Common.h"
+#include "AKFS_Disp.h"
+#include "AKFS_FileIO.h"
+#include "AKFS_APIs.h"
+
+#ifdef WIN32
+#include "AK8975_LinuxDriver.h"
+#endif
+
+static AK8975PRMS g_prms;
+
+/*!
+ Initialize library. At first, 0 is set to all parameters. After that, some
+ parameters, which should not be 0, are set to specific value. Some of initial
+ values can be customized by editing the file \c "AKFS_CSpec.h".
+ @return The return value is #AKM_SUCCESS.
+ @param[in] hpat Specify a layout pattern number. The number is determined
+ according to the mount orientation of the magnetometer.
+ @param[in] regs[3] Specify the ASA values which are read out from
+ fuse ROM. regs[0] is ASAX, regs[1] is ASAY, regs[2] is ASAZ.
+ */
+int16 AKFS_Init(
+ const AKFS_PATNO hpat,
+ const uint8 regs[]
+)
+{
+ AKMDATA(AKMDATA_DUMP, "%s: hpat=%d, r[0]=0x%02X, r[1]=0x%02X, r[2]=0x%02X\n",
+ __FUNCTION__, hpat, regs[0], regs[1], regs[2]);
+
+ /* Set 0 to the AK8975 structure. */
+ memset(&g_prms, 0, sizeof(AK8975PRMS));
+
+ /* Sensitivity */
+ g_prms.mfv_hs.u.x = AK8975_HSENSE_DEFAULT;
+ g_prms.mfv_hs.u.y = AK8975_HSENSE_DEFAULT;
+ g_prms.mfv_hs.u.z = AK8975_HSENSE_DEFAULT;
+ g_prms.mfv_as.u.x = AK8975_ASENSE_DEFAULT;
+ g_prms.mfv_as.u.y = AK8975_ASENSE_DEFAULT;
+ g_prms.mfv_as.u.z = AK8975_ASENSE_DEFAULT;
+
+ /* Initialize variables that initial value is not 0. */
+ g_prms.mi_hnaveV = CSPEC_HNAVE_V;
+ g_prms.mi_hnaveD = CSPEC_HNAVE_D;
+ g_prms.mi_anaveV = CSPEC_ANAVE_V;
+ g_prms.mi_anaveD = CSPEC_ANAVE_D;
+
+ /* Copy ASA values */
+ g_prms.mi_asa.u.x = regs[0];
+ g_prms.mi_asa.u.y = regs[1];
+ g_prms.mi_asa.u.z = regs[2];
+
+ /* Copy layout pattern */
+ g_prms.m_hpat = hpat;
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ Release resources. This function is for future expansion.
+ @return The return value is #AKM_SUCCESS.
+ */
+int16 AKFS_Release(void)
+{
+ return AKM_SUCCESS;
+}
+
+/*
+ This function is called just before a measurement sequence starts.
+ This function reads parameters from file, then initializes algorithm
+ parameters.
+ @return The return value is #AKM_SUCCESS.
+ @param[in] path Specify a path to the settings file.
+ */
+int16 AKFS_Start(
+ const char* path
+)
+{
+ AKMDATA(AKMDATA_DUMP, "%s: path=%s\n", __FUNCTION__, path);
+
+ /* Read setting files from a file */
+ if (AKFS_LoadParameters(&g_prms, path) != AKM_SUCCESS) {
+ AKMERROR_STR("AKFS_Load");
+ }
+
+ /* Initialize buffer */
+ AKFS_InitBuffer(AKFS_HDATA_SIZE, g_prms.mfv_hdata);
+ AKFS_InitBuffer(AKFS_HDATA_SIZE, g_prms.mfv_hvbuf);
+ AKFS_InitBuffer(AKFS_ADATA_SIZE, g_prms.mfv_adata);
+ AKFS_InitBuffer(AKFS_ADATA_SIZE, g_prms.mfv_avbuf);
+
+ /* Initialize for AOC */
+ AKFS_InitAOC(&g_prms.m_aocv);
+ /* Initialize magnetic status */
+ g_prms.mi_hstatus = 0;
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ This function is called when a measurement sequence is done.
+ This fucntion writes parameters to file.
+ @return The return value is #AKM_SUCCESS.
+ @param[in] path Specify a path to the settings file.
+ */
+int16 AKFS_Stop(
+ const char* path
+)
+{
+ AKMDATA(AKMDATA_DUMP, "%s: path=%s\n", __FUNCTION__, path);
+
+ /* Write setting files to a file */
+ if (AKFS_SaveParameters(&g_prms, path) != AKM_SUCCESS) {
+ AKMERROR_STR("AKFS_Save");
+ }
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ This function is called when new magnetometer data is available. The output
+ vector format and coordination system follow the Android definition.
+ @return The return value is #AKM_SUCCESS.
+ Otherwise the return value is #AKM_FAIL.
+ @param[in] mag A set of measurement data from magnetometer. X axis value
+ should be in mag[0], Y axis value should be in mag[1], Z axis value should be
+ in mag[2].
+ @param[in] status A status of magnetometer. This status indicates the result
+ of measurement data, i.e. overflow, success or fail, etc.
+ @param[out] vx X axis value of magnetic field vector.
+ @param[out] vy Y axis value of magnetic field vector.
+ @param[out] vz Z axis value of magnetic field vector.
+ @param[out] accuracy Accuracy of magnetic field vector.
+ */
+int16 AKFS_Get_MAGNETIC_FIELD(
+ const int16 mag[3],
+ const int16 status,
+ AKFLOAT* vx,
+ AKFLOAT* vy,
+ AKFLOAT* vz,
+ int16* accuracy
+)
+{
+ int16 akret;
+ int16 aocret;
+ AKFLOAT radius;
+
+ AKMDATA(AKMDATA_DUMP, "%s: m[0]=%d, m[1]=%d, m[2]=%d, st=%d\n",
+ __FUNCTION__, mag[0], mag[1], mag[2], status);
+
+ /* Decomposition */
+ /* Sensitivity adjustment, i.e. multiply ASA, is done in this function. */
+ akret = AKFS_DecompAK8975(
+ mag,
+ status,
+ &g_prms.mi_asa,
+ AKFS_HDATA_SIZE,
+ g_prms.mfv_hdata
+ );
+ if(akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Adjust coordination */
+ akret = AKFS_Rotate(
+ g_prms.m_hpat,
+ &g_prms.mfv_hdata[0]
+ );
+ if (akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* AOC for magnetometer */
+ /* Offset estimation is done in this function */
+ aocret = AKFS_AOC(
+ &g_prms.m_aocv,
+ g_prms.mfv_hdata,
+ &g_prms.mfv_ho
+ );
+
+ /* Subtract offset */
+ /* Then, a magnetic vector, the unit is uT, is stored in mfv_hvbuf. */
+ akret = AKFS_VbNorm(
+ AKFS_HDATA_SIZE,
+ g_prms.mfv_hdata,
+ 1,
+ &g_prms.mfv_ho,
+ &g_prms.mfv_hs,
+ AK8975_HSENSE_TARGET,
+ AKFS_HDATA_SIZE,
+ g_prms.mfv_hvbuf
+ );
+ if(akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Averaging */
+ akret = AKFS_VbAve(
+ AKFS_HDATA_SIZE,
+ g_prms.mfv_hvbuf,
+ CSPEC_HNAVE_V,
+ &g_prms.mfv_hvec
+ );
+ if (akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Check the size of magnetic vector */
+ radius = AKFS_SQRT(
+ (g_prms.mfv_hvec.u.x * g_prms.mfv_hvec.u.x) +
+ (g_prms.mfv_hvec.u.y * g_prms.mfv_hvec.u.y) +
+ (g_prms.mfv_hvec.u.z * g_prms.mfv_hvec.u.z));
+
+ if (radius > AKFS_GEOMAG_MAX) {
+ g_prms.mi_hstatus = 0;
+ } else {
+ if (aocret) {
+ g_prms.mi_hstatus = 3;
+ }
+ }
+
+ *vx = g_prms.mfv_hvec.u.x;
+ *vy = g_prms.mfv_hvec.u.y;
+ *vz = g_prms.mfv_hvec.u.z;
+ *accuracy = g_prms.mi_hstatus;
+
+ /* Debug output */
+ AKMDATA(AKMDATA_MAG, "Mag(%d):%8.2f, %8.2f, %8.2f\n",
+ *accuracy, *vx, *vy, *vz);
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ This function is called when new accelerometer data is available. The output
+ vector format and coordination system follow the Android definition.
+ @return The return value is #AKM_SUCCESS when function succeeds. Otherwise
+ the return value is #AKM_FAIL.
+ @param[in] acc A set of measurement data from accelerometer. X axis value
+ should be in acc[0], Y axis value should be in acc[1], Z axis value should be
+ in acc[2].
+ @param[in] status A status of accelerometer. This status indicates the result
+ of acceleration data, i.e. overflow, success or fail, etc.
+ @param[out] vx X axis value of acceleration vector.
+ @param[out] vy Y axis value of acceleration vector.
+ @param[out] vz Z axis value of acceleration vector.
+ @param[out] accuracy Accuracy of acceleration vector.
+ This value is always 3.
+ */
+int16 AKFS_Get_ACCELEROMETER(
+ const int16 acc[3],
+ const int16 status,
+ AKFLOAT* vx,
+ AKFLOAT* vy,
+ AKFLOAT* vz,
+ int16* accuracy
+)
+{
+ int16 akret;
+
+ AKMDATA(AKMDATA_DUMP, "%s: a[0]=%d, a[1]=%d, a[2]=%d, st=%d\n",
+ __FUNCTION__, acc[0], acc[1], acc[2], status);
+
+ /* Save data to buffer */
+ AKFS_BufShift(
+ AKFS_ADATA_SIZE,
+ 1,
+ g_prms.mfv_adata
+ );
+ g_prms.mfv_adata[0].u.x = acc[0];
+ g_prms.mfv_adata[0].u.y = acc[1];
+ g_prms.mfv_adata[0].u.z = acc[2];
+
+ /* Subtract offset, adjust sensitivity */
+ /* As a result, a unit of acceleration data in mfv_avbuf is '1G = 9.8' */
+ akret = AKFS_VbNorm(
+ AKFS_ADATA_SIZE,
+ g_prms.mfv_adata,
+ 1,
+ &g_prms.mfv_ao,
+ &g_prms.mfv_as,
+ AK8975_ASENSE_TARGET,
+ AKFS_ADATA_SIZE,
+ g_prms.mfv_avbuf
+ );
+ if(akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Averaging */
+ akret = AKFS_VbAve(
+ AKFS_ADATA_SIZE,
+ g_prms.mfv_avbuf,
+ CSPEC_ANAVE_V,
+ &g_prms.mfv_avec
+ );
+ if (akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Adjust coordination */
+ /* It is not needed. Because, the data from AK8975 driver is already
+ follows Android coordinate system. */
+
+ *vx = g_prms.mfv_avec.u.x;
+ *vy = g_prms.mfv_avec.u.y;
+ *vz = g_prms.mfv_avec.u.z;
+ *accuracy = 3;
+
+ /* Debug output */
+ AKMDATA(AKMDATA_ACC, "Acc(%d):%8.2f, %8.2f, %8.2f\n",
+ *accuracy, *vx, *vy, *vz);
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ Get orientation sensor's elements. The vector format and coordination system
+ follow the Android definition. Before this function is called, magnetic
+ field vector and acceleration vector should be stored in the buffer by
+ calling #AKFS_Get_MAGNETIC_FIELD and #AKFS_Get_ACCELEROMETER.
+ @return The return value is #AKM_SUCCESS when function succeeds. Otherwise
+ the return value is #AKM_FAIL.
+ @param[out] azimuth Azimuthal angle in degree.
+ @param[out] pitch Pitch angle in degree.
+ @param[out] roll Roll angle in degree.
+ @param[out] accuracy Accuracy of orientation sensor.
+ */
+int16 AKFS_Get_ORIENTATION(
+ AKFLOAT* azimuth,
+ AKFLOAT* pitch,
+ AKFLOAT* roll,
+ int16* accuracy
+)
+{
+ int16 akret;
+
+ /* Azimuth calculation */
+ /* Coordination system follows the Android coordination. */
+ akret = AKFS_Direction(
+ AKFS_HDATA_SIZE,
+ g_prms.mfv_hvbuf,
+ CSPEC_HNAVE_D,
+ AKFS_ADATA_SIZE,
+ g_prms.mfv_avbuf,
+ CSPEC_ANAVE_D,
+ &g_prms.mf_azimuth,
+ &g_prms.mf_pitch,
+ &g_prms.mf_roll
+ );
+
+ if(akret == AKFS_ERROR) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+ *azimuth = g_prms.mf_azimuth;
+ *pitch = g_prms.mf_pitch;
+ *roll = g_prms.mf_roll;
+ *accuracy = g_prms.mi_hstatus;
+
+ /* Debug output */
+ AKMDATA(AKMDATA_ORI, "Ori(%d):%8.2f, %8.2f, %8.2f\n",
+ *accuracy, *azimuth, *pitch, *roll);
+
+ return AKM_SUCCESS;
+}
+
diff --git a/sensors/akmdfs/AKFS_APIs.h b/sensors/akmdfs/AKFS_APIs.h
new file mode 100644
index 0000000..e4d1e48
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs.h
@@ -0,0 +1,69 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_APIS_H
+#define AKFS_INC_APIS_H
+
+/* Include files for AK8975 library. */
+#include "AKFS_Compass.h"
+
+/*** Constant definition ******************************************************/
+#define AKFS_GEOMAG_MAX 70
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+int16 AKFS_Init(
+ const AKFS_PATNO hpat,
+ const uint8 regs[]
+);
+
+int16 AKFS_Release(void);
+
+int16 AKFS_Start(const char* path);
+
+int16 AKFS_Stop(const char* path);
+
+int16 AKFS_Get_MAGNETIC_FIELD(
+ const int16 mag[3],
+ const int16 status,
+ AKFLOAT* vx,
+ AKFLOAT* vy,
+ AKFLOAT* vz,
+ int16* accuracy
+);
+
+int16 AKFS_Get_ACCELEROMETER(
+ const int16 acc[3],
+ const int16 status,
+ AKFLOAT* vx,
+ AKFLOAT* vy,
+ AKFLOAT* vz,
+ int16* accuracy
+);
+
+int16 AKFS_Get_ORIENTATION(
+ AKFLOAT* azimuth,
+ AKFLOAT* pitch,
+ AKFLOAT* roll,
+ int16* accuracy
+);
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.c b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.c
new file mode 100644
index 0000000..7bac9a1
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.c
@@ -0,0 +1,44 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_AK8975.h"
+#include "AKFS_Device.h"
+
+/*!
+ */
+int16 AKFS_DecompAK8975(
+ const int16 mag[3],
+ const int16 status,
+ const uint8vec* asa,
+ const int16 nhdata,
+ AKFVEC hdata[]
+)
+{
+ /* put st1 and st2 value */
+ if (AK8975_ST_ERROR(status)) {
+ return AKFS_ERROR;
+ }
+
+ /* magnetic */
+ AKFS_BufShift(nhdata, 1, hdata);
+ hdata[0].u.x = mag[0] * (((asa->u.x)/256.0f) + 0.5f);
+ hdata[0].u.y = mag[1] * (((asa->u.y)/256.0f) + 0.5f);
+ hdata[0].u.z = mag[2] * (((asa->u.z)/256.0f) + 0.5f);
+
+ return AKFS_SUCCESS;
+}
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.h
new file mode 100644
index 0000000..25459e3
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AK8975.h
@@ -0,0 +1,50 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_AK8975_H
+#define AKFS_INC_AK8975_H
+
+#include "AKFS_Device.h"
+
+/***** Constant definition ****************************************************/
+#define AK8975_BDATA_SIZE 8
+
+#define AK8975_HSENSE_DEFAULT 1
+#define AK8975_HSENSE_TARGET 0.3f
+#define AK8975_ASENSE_DEFAULT 720
+#define AK8975_ASENSE_TARGET 9.80665f
+
+#define AK8975_HDATA_CONVERTER(hi, low, asa) \
+ (AKFLOAT)((int16)((((uint16)(hi))<<8)+(uint16)(low))*(((asa)/256.0f) + 0.5f))
+
+#define AK8975_ST_ERROR(st) (((st)&0x09) != 0x01)
+
+/***** Type declaration *******************************************************/
+
+/***** Prototype of function **************************************************/
+AKLIB_C_API_START
+int16 AKFS_DecompAK8975(
+ const int16 mag[3],
+ const int16 status,
+ const uint8vec* asa,
+ const int16 nhdata,
+ AKFVEC hdata[]
+);
+AKLIB_C_API_END
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.c b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.c
new file mode 100644
index 0000000..62b2361
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.c
@@ -0,0 +1,333 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_AOC.h"
+#include "AKFS_Math.h"
+
+/*
+ * CalcR
+ */
+static AKFLOAT CalcR(
+ const AKFVEC* x,
+ const AKFVEC* y
+){
+ int16 i;
+ AKFLOAT r;
+
+ r = 0.0;
+ for(i = 0; i < 3; i++){
+ r += (x->v[i]-y->v[i]) * (x->v[i]-y->v[i]);
+ }
+ r = sqrt(r);
+
+ return r;
+}
+
+/*
+ * From4Points2Sphere()
+ */
+static int16 From4Points2Sphere(
+ const AKFVEC points[], /*! (i/o) : input vectors */
+ AKFVEC* center, /*! (o) : center of sphere */
+ AKFLOAT* r /*! (i) : add/subtract value */
+){
+ AKFLOAT dif[3][3];
+ AKFLOAT r2[3];
+
+ AKFLOAT A;
+ AKFLOAT B;
+ AKFLOAT C;
+ AKFLOAT D;
+ AKFLOAT E;
+ AKFLOAT F;
+ AKFLOAT G;
+
+ AKFLOAT OU;
+ AKFLOAT OD;
+
+ int16 i, j;
+
+ for(i = 0; i < 3; i++){
+ r2[i] = 0.0;
+ for(j = 0; j < 3; j++){
+ dif[i][j] = points[i].v[j] - points[3].v[j];
+ r2[i] += (points[i].v[j]*points[i].v[j]
+ - points[3].v[j]*points[3].v[j]);
+ }
+ r2[i] *= 0.5;
+ }
+
+ A = dif[0][0]*dif[2][2] - dif[0][2]*dif[2][0];
+ B = dif[0][1]*dif[2][0] - dif[0][0]*dif[2][1];
+ C = dif[0][0]*dif[2][1] - dif[0][1]*dif[2][0];
+ D = dif[0][0]*r2[2] - dif[2][0]*r2[0];
+ E = dif[0][0]*dif[1][1] - dif[0][1]*dif[1][0];
+ F = dif[1][0]*dif[0][2] - dif[0][0]*dif[1][2];
+ G = dif[0][0]*r2[1] - dif[1][0]*r2[0];
+
+ OU = D*E + B*G;
+ OD = C*F + A*E;
+
+ if(fabs(OD) < AKFS_EPSILON){
+ return -1;
+ }
+
+ center->v[2] = OU / OD;
+
+ OU = F*center->v[2] + G;
+ OD = E;
+
+ if(fabs(OD) < AKFS_EPSILON){
+ return -1;
+ }
+
+ center->v[1] = OU / OD;
+
+ OU = r2[0] - dif[0][1]*center->v[1] - dif[0][2]*center->v[2];
+ OD = dif[0][0];
+
+ if(fabs(OD) < AKFS_EPSILON){
+ return -1;
+ }
+
+ center->v[0] = OU / OD;
+
+ *r = CalcR(&points[0], center);
+
+ return 0;
+
+}
+
+/*
+ * MeanVar
+ */
+static void MeanVar(
+ const AKFVEC v[], /*!< (i) : input vectors */
+ const int16 n, /*!< (i) : number of vectors */
+ AKFVEC* mean, /*!< (o) : (max+min)/2 */
+ AKFVEC* var /*!< (o) : variation in vectors */
+){
+ int16 i;
+ int16 j;
+ AKFVEC max;
+ AKFVEC min;
+
+ for(j = 0; j < 3; j++){
+ min.v[j] = v[0].v[j];
+ max.v[j] = v[0].v[j];
+ for(i = 1; i < n; i++){
+ if(v[i].v[j] < min.v[j]){
+ min.v[j] = v[i].v[j];
+ }
+ if(v[i].v[j] > max.v[j]){
+ max.v[j] = v[i].v[j];
+ }
+ }
+ mean->v[j] = (max.v[j] + min.v[j]) / 2.0; /*mean */
+ var->v[j] = max.v[j] - min.v[j]; /*var */
+ }
+}
+
+/*
+ * Get4points
+ */
+static void Get4points(
+ const AKFVEC v[], /*!< (i) : input vectors */
+ const int16 n, /*!< (i) : number of vectors */
+ AKFVEC out[] /*!< (o) : */
+){
+ int16 i, j;
+ AKFLOAT temp;
+ AKFLOAT d;
+
+ AKFVEC dv[AKFS_HBUF_SIZE];
+ AKFVEC cross;
+ AKFVEC tempv;
+
+ /* out 0 */
+ out[0] = v[0];
+
+ /* out 1 */
+ d = 0.0;
+ for(i = 1; i < n; i++){
+ temp = CalcR(&v[i], &out[0]);
+ if(d < temp){
+ d = temp;
+ out[1] = v[i];
+ }
+ }
+
+ /* out 2 */
+ d = 0.0;
+ for(j = 0; j < 3; j++){
+ dv[0].v[j] = out[1].v[j] - out[0].v[j];
+ }
+ for(i = 1; i < n; i++){
+ for(j = 0; j < 3; j++){
+ dv[i].v[j] = v[i].v[j] - out[0].v[j];
+ }
+ tempv.v[0] = dv[0].v[1]*dv[i].v[2] - dv[0].v[2]*dv[i].v[1];
+ tempv.v[1] = dv[0].v[2]*dv[i].v[0] - dv[0].v[0]*dv[i].v[2];
+ tempv.v[2] = dv[0].v[0]*dv[i].v[1] - dv[0].v[1]*dv[i].v[0];
+ temp = tempv.u.x * tempv.u.x
+ + tempv.u.y * tempv.u.y
+ + tempv.u.z * tempv.u.z;
+ if(d < temp){
+ d = temp;
+ out[2] = v[i];
+ cross = tempv;
+ }
+ }
+
+ /* out 3 */
+ d = 0.0;
+ for(i = 1; i < n; i++){
+ temp = dv[i].u.x * cross.u.x
+ + dv[i].u.y * cross.u.y
+ + dv[i].u.z * cross.u.z;
+ temp = fabs(temp);
+ if(d < temp){
+ d = temp;
+ out[3] = v[i];
+ }
+ }
+}
+
+/*
+ * CheckInitFvec
+ */
+static int16 CheckInitFvec(
+ const AKFVEC *v /*!< [in] vector */
+){
+ int16 i;
+
+ for(i = 0; i < 3; i++){
+ if(AKFS_FMAX <= v->v[i]){
+ return 1; /* initvalue */
+ }
+ }
+
+ return 0; /* not initvalue */
+}
+
+/*
+ * AKFS_AOC
+ */
+int16 AKFS_AOC( /*!< (o) : calibration success(1), failure(0) */
+ AKFS_AOC_VAR* haocv, /*!< (i/o) : a set of variables */
+ const AKFVEC* hdata, /*!< (i) : vectors of data */
+ AKFVEC* ho /*!< (i/o) : offset */
+){
+ int16 i, j;
+ int16 num;
+ AKFLOAT tempf;
+ AKFVEC tempho;
+
+ AKFVEC fourpoints[4];
+
+ AKFVEC var;
+ AKFVEC mean;
+
+ /* buffer new data */
+ for(i = 1; i < AKFS_HBUF_SIZE; i++){
+ haocv->hbuf[AKFS_HBUF_SIZE-i] = haocv->hbuf[AKFS_HBUF_SIZE-i-1];
+ }
+ haocv->hbuf[0] = *hdata;
+
+ /* Check Init */
+ num = 0;
+ for(i = AKFS_HBUF_SIZE; 3 < i; i--){
+ if(CheckInitFvec(&haocv->hbuf[i-1]) == 0){
+ num = i;
+ break;
+ }
+ }
+ if(num < 4){
+ return AKFS_ERROR;
+ }
+
+ /* get 4 points */
+ Get4points(haocv->hbuf, num, fourpoints);
+
+ /* estimate offset */
+ if(0 != From4Points2Sphere(fourpoints, &tempho, &haocv->hraoc)){
+ return AKFS_ERROR;
+ }
+
+ /* check distance */
+ for(i = 0; i < 4; i++){
+ for(j = (i+1); j < 4; j++){
+ tempf = CalcR(&fourpoints[i], &fourpoints[j]);
+ if((tempf < haocv->hraoc)||(tempf < AKFS_HR_TH)){
+ return AKFS_ERROR;
+ }
+ }
+ }
+
+ /* update offset buffer */
+ for(i = 1; i < AKFS_HOBUF_SIZE; i++){
+ haocv->hobuf[AKFS_HOBUF_SIZE-i] = haocv->hobuf[AKFS_HOBUF_SIZE-i-1];
+ }
+ haocv->hobuf[0] = tempho;
+
+ /* clear hbuf */
+ for(i = (AKFS_HBUF_SIZE>>1); i < AKFS_HBUF_SIZE; i++) {
+ for(j = 0; j < 3; j++) {
+ haocv->hbuf[i].v[j]= AKFS_FMAX;
+ }
+ }
+
+ /* Check Init */
+ if(CheckInitFvec(&haocv->hobuf[AKFS_HOBUF_SIZE-1]) == 1){
+ return AKFS_ERROR;
+ }
+
+ /* Check ovar */
+ tempf = haocv->hraoc * AKFS_HO_TH;
+ MeanVar(haocv->hobuf, AKFS_HOBUF_SIZE, &mean, &var);
+ if ((var.u.x >= tempf) || (var.u.y >= tempf) || (var.u.z >= tempf)){
+ return AKFS_ERROR;
+ }
+
+ *ho = mean;
+
+ return AKFS_SUCCESS;
+}
+
+/*
+ * AKFS_InitAOC
+ */
+void AKFS_InitAOC(
+ AKFS_AOC_VAR* haocv
+){
+ int16 i, j;
+
+ /* Initialize buffer */
+ for(i = 0; i < AKFS_HBUF_SIZE; i++) {
+ for(j = 0; j < 3; j++) {
+ haocv->hbuf[i].v[j]= AKFS_FMAX;
+ }
+ }
+ for(i = 0; i < AKFS_HOBUF_SIZE; i++) {
+ for(j = 0; j < 3; j++) {
+ haocv->hobuf[i].v[j]= AKFS_FMAX;
+ }
+ }
+
+ haocv->hraoc = 0.0;
+}
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.h
new file mode 100644
index 0000000..ffaaa88
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_AOC.h
@@ -0,0 +1,53 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_AOC_H
+#define AKFS_INC_AOC_H
+
+#include "AKFS_Device.h"
+
+/***** Constant definition ****************************************************/
+#define AKFS_HBUF_SIZE 20
+#define AKFS_HOBUF_SIZE 4
+#define AKFS_HR_TH 10
+#define AKFS_HO_TH 0.15
+
+/***** Macro definition *******************************************************/
+
+/***** Type declaration *******************************************************/
+typedef struct _AKFS_AOC_VAR{
+ AKFVEC hbuf[AKFS_HBUF_SIZE];
+ AKFVEC hobuf[AKFS_HOBUF_SIZE];
+ AKFLOAT hraoc;
+} AKFS_AOC_VAR;
+
+/***** Prototype of function **************************************************/
+AKLIB_C_API_START
+int16 AKFS_AOC(
+ AKFS_AOC_VAR* haocv,
+ const AKFVEC* hdata,
+ AKFVEC* ho
+);
+
+void AKFS_InitAOC(
+ AKFS_AOC_VAR* haocv
+);
+
+AKLIB_C_API_END
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_Configure.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Configure.h
new file mode 100644
index 0000000..1f80f48
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Configure.h
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_CONFIG_H
+#define AKFS_INC_CONFIG_H
+
+/***** Language configuration *************************************************/
+#if defined(__cplusplus)
+#define AKLIB_C_API_START extern "C" {
+#define AKLIB_C_API_END }
+#else
+#define AKLIB_C_API_START
+#define AKLIB_C_API_END
+#endif
+
+/*! If following line is commented in, double type is used for floating point
+ calculation */
+/*
+#define AKFS_PRECISION_DOUBLE
+*/
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.c b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.c
new file mode 100644
index 0000000..3d99ab1
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.c
@@ -0,0 +1,110 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_Device.h"
+
+int16 AKFS_InitBuffer(
+ const int16 ndata, /*!< Size of vector buffer */
+ AKFVEC vdata[] /*!< Vector buffer */
+)
+{
+ int i;
+
+ /* size check */
+ if (ndata <= 0) {
+ return AKFS_ERROR;
+ }
+
+ for (i=0; i<ndata; i++) {
+ vdata[i].u.x = AKFS_INIT_VALUE_F;
+ vdata[i].u.y = AKFS_INIT_VALUE_F;
+ vdata[i].u.z = AKFS_INIT_VALUE_F;
+ }
+
+ return AKFS_SUCCESS;
+}
+
+int16 AKFS_BufShift(
+ const int16 len, /*!< size of buffer */
+ const int16 shift, /*!< shift size */
+ AKFVEC v[] /*!< buffer */
+)
+{
+ int16 i;
+
+ if((shift < 1) || (len < shift)) {
+ return AKFS_ERROR;
+ }
+ for (i = len-1; i >= shift; i--) {
+ v[i] = v[i-shift];
+ }
+ return AKFS_SUCCESS;
+}
+
+int16 AKFS_Rotate(
+ const AKFS_PATNO pat,
+ AKFVEC* vec
+)
+{
+ AKFLOAT tmp;
+ switch(pat){
+ /* Obverse */
+ case PAT1:
+ /* This is Android default */
+ break;
+ case PAT2:
+ tmp = vec->u.x;
+ vec->u.x = vec->u.y;
+ vec->u.y = -tmp;
+ break;
+ case PAT3:
+ vec->u.x = -(vec->u.x);
+ vec->u.y = -(vec->u.y);
+ break;
+ case PAT4:
+ tmp = vec->u.x;
+ vec->u.x = -(vec->u.y);
+ vec->u.y = tmp;
+ break;
+ /* Reverse */
+ case PAT5:
+ vec->u.x = -(vec->u.x);
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT6:
+ tmp = vec->u.x;
+ vec->u.x = vec->u.y;
+ vec->u.y = tmp;
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT7:
+ vec->u.y = -(vec->u.y);
+ vec->u.z = -(vec->u.z);
+ break;
+ case PAT8:
+ tmp = vec->u.x;
+ vec->u.x = -(vec->u.y);
+ vec->u.y = -tmp;
+ vec->u.z = -(vec->u.z);
+ break;
+ default:
+ return AKFS_ERROR;
+ }
+
+ return AKFS_SUCCESS;
+}
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.h
new file mode 100644
index 0000000..0292d54
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Device.h
@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_DEVICE_H
+#define AKFS_INC_DEVICE_H
+
+#include <float.h>
+#include "AKFS_Configure.h"
+
+/***** Constant definition ****************************************************/
+#define AKFS_ERROR 0
+#define AKFS_SUCCESS 1
+
+#define AKFS_HDATA_SIZE 32
+#define AKFS_ADATA_SIZE 32
+
+/***** Type declaration *******************************************************/
+typedef signed char int8;
+typedef signed short int16;
+typedef unsigned char uint8;
+typedef unsigned short uint16;
+
+
+#ifdef AKFS_PRECISION_DOUBLE
+typedef double AKFLOAT;
+#define AKFS_EPSILON DBL_EPSILON
+#define AKFS_FMAX DBL_MAX
+#define AKFS_FMIN DBL_MIN
+
+#else
+typedef float AKFLOAT;
+#define AKFS_EPSILON FLT_EPSILON
+#define AKFS_FMAX FLT_MAX
+#define AKFS_FMIN FLT_MIN
+
+#endif
+
+/* Treat maximum value as initial value */
+#define AKFS_INIT_VALUE_F AKFS_FMAX
+
+/***** Vector *****/
+typedef union _uint8vec{
+ struct {
+ uint8 x;
+ uint8 y;
+ uint8 z;
+ }u;
+ uint8 v[3];
+} uint8vec;
+
+typedef union _AKFVEC{
+ struct {
+ AKFLOAT x;
+ AKFLOAT y;
+ AKFLOAT z;
+ }u;
+ AKFLOAT v[3];
+} AKFVEC;
+
+/***** Layout pattern *****/
+typedef enum _AKFS_PATNO {
+ PAT_INVALID = 0,
+ PAT1, /* obverse: 1st pin is right down */
+ PAT2, /* obverse: 1st pin is left down */
+ PAT3, /* obverse: 1st pin is left top */
+ PAT4, /* obverse: 1st pin is right top */
+ PAT5, /* reverse: 1st pin is left down (from top view) */
+ PAT6, /* reverse: 1st pin is left top (from top view) */
+ PAT7, /* reverse: 1st pin is right top (from top view) */
+ PAT8 /* reverse: 1st pin is right down (from top view) */
+} AKFS_PATNO;
+
+/***** Prototype of function **************************************************/
+AKLIB_C_API_START
+int16 AKFS_InitBuffer(
+ const int16 ndata, /*!< Size of raw vector buffer */
+ AKFVEC vdata[] /*!< Raw vector buffer */
+);
+
+int16 AKFS_BufShift(
+ const int16 len,
+ const int16 shift,
+ AKFVEC v[]
+);
+
+int16 AKFS_Rotate(
+ const AKFS_PATNO pat,
+ AKFVEC* vec
+);
+AKLIB_C_API_END
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.c b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.c
new file mode 100644
index 0000000..f47e930
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.c
@@ -0,0 +1,133 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_Direction.h"
+#include "AKFS_VNorm.h"
+#include "AKFS_Math.h"
+
+/*
+ Coordinate system is right-handed.
+ X-Axis: from left to right.
+ Y-Axis: from bottom to top.
+ Z-Axis: from reverse to obverse.
+
+ azimuth: Rotaion around Z axis, with positive values
+ when y-axis moves toward the x-axis.
+ pitch: Rotation around X axis, with positive values
+ when z-axis moves toward the y-axis.
+ roll: Rotation around Y axis, with positive values
+ when x-axis moves toward the z-axis.
+*/
+
+/*
+ This function is used internaly, so output is RADIAN!
+ */
+static void AKFS_Angle(
+ const AKFVEC* avec,
+ AKFLOAT* pitch, /* radian */
+ AKFLOAT* roll /* radian */
+)
+{
+ AKFLOAT av; /* Size of vector */
+
+ av = AKFS_SQRT((avec->u.x)*(avec->u.x) + (avec->u.y)*(avec->u.y) + (avec->u.z)*(avec->u.z));
+
+ *pitch = AKFS_ASIN(-(avec->u.y) / av);
+ *roll = AKFS_ASIN((avec->u.x) / av);
+}
+
+/*
+ This function is used internaly, so output is RADIAN!
+ */
+static void AKFS_Azimuth(
+ const AKFVEC* hvec,
+ const AKFLOAT pitch, /* radian */
+ const AKFLOAT roll, /* radian */
+ AKFLOAT* azimuth /* radian */
+)
+{
+ AKFLOAT sinP; /* sin value of pitch angle */
+ AKFLOAT cosP; /* cos value of pitch angle */
+ AKFLOAT sinR; /* sin value of roll angle */
+ AKFLOAT cosR; /* cos value of roll angle */
+ AKFLOAT Xh; /* X axis element of vector which is projected to horizontal plane */
+ AKFLOAT Yh; /* Y axis element of vector which is projected to horizontal plane */
+
+ sinP = AKFS_SIN(pitch);
+ cosP = AKFS_COS(pitch);
+ sinR = AKFS_SIN(roll);
+ cosR = AKFS_COS(roll);
+
+ Yh = -(hvec->u.x)*cosR + (hvec->u.z)*sinR;
+ Xh = (hvec->u.x)*sinP*sinR + (hvec->u.y)*cosP + (hvec->u.z)*sinP*cosR;
+
+ /* atan2(y, x) -> divisor and dividend is opposite from mathematical equation. */
+ *azimuth = AKFS_ATAN2(Yh, Xh);
+}
+
+int16 AKFS_Direction(
+ const int16 nhvec,
+ const AKFVEC hvec[],
+ const int16 hnave,
+ const int16 navec,
+ const AKFVEC avec[],
+ const int16 anave,
+ AKFLOAT* azimuth,
+ AKFLOAT* pitch,
+ AKFLOAT* roll
+)
+{
+ AKFVEC have, aave;
+ AKFLOAT azimuthRad;
+ AKFLOAT pitchRad;
+ AKFLOAT rollRad;
+
+ /* arguments check */
+ if ((nhvec <= 0) || (navec <= 0) || (hnave <= 0) || (anave <= 0)) {
+ return AKFS_ERROR;
+ }
+ if ((nhvec < hnave) || (navec < anave)) {
+ return AKFS_ERROR;
+ }
+
+ /* average */
+ if (AKFS_VbAve(nhvec, hvec, hnave, &have) != AKFS_SUCCESS) {
+ return AKFS_ERROR;
+ }
+ if (AKFS_VbAve(navec, avec, anave, &aave) != AKFS_SUCCESS) {
+ return AKFS_ERROR;
+ }
+
+ /* calculate pitch and roll */
+ AKFS_Angle(&aave, &pitchRad, &rollRad);
+
+ /* calculate azimuth */
+ AKFS_Azimuth(&have, pitchRad, rollRad, &azimuthRad);
+
+ *azimuth = RAD2DEG(azimuthRad);
+ *pitch = RAD2DEG(pitchRad);
+ *roll = RAD2DEG(rollRad);
+
+ /* Adjust range of azimuth */
+ if (*azimuth < 0) {
+ *azimuth += 360.0f;
+ }
+
+ return AKFS_SUCCESS;
+}
+
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.h
new file mode 100644
index 0000000..c08338d
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Direction.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_DIRECTION_H
+#define AKFS_INC_DIRECTION_H
+
+#include "AKFS_Device.h"
+
+/***** Prototype of function **************************************************/
+AKLIB_C_API_START
+int16 AKFS_Direction(
+ const int16 nhvec,
+ const AKFVEC hvec[],
+ const int16 hnave,
+ const int16 navec,
+ const AKFVEC avec[],
+ const int16 anave,
+ AKFLOAT* azimuth,
+ AKFLOAT* pitch,
+ AKFLOAT* roll
+);
+AKLIB_C_API_END
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_Math.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Math.h
new file mode 100644
index 0000000..dfe48b3
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_Math.h
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_MATH_H
+#define AKFS_INC_MATH_H
+
+#include <math.h>
+#include "AKFS_Configure.h"
+
+/***** Constant definition ****************************************************/
+#define AKFS_PI 3.141592654f
+#define RAD2DEG(rad) ((rad)*180.0f/AKFS_PI)
+
+/***** Macro definition *******************************************************/
+
+#ifdef AKFS_PRECISION_DOUBLE
+#define AKFS_SIN(x) sin(x)
+#define AKFS_COS(x) cos(x)
+#define AKFS_ASIN(x) asin(x)
+#define AKFS_ACOS(x) acos(x)
+#define AKFS_ATAN2(y, x) atan2((y), (x))
+#define AKFS_SQRT(x) sqrt(x)
+#else
+#define AKFS_SIN(x) sinf(x)
+#define AKFS_COS(x) cosf(x)
+#define AKFS_ASIN(x) asinf(x)
+#define AKFS_ACOS(x) acosf(x)
+#define AKFS_ATAN2(y, x) atan2f((y), (x))
+#define AKFS_SQRT(x) sqrtf(x)
+#endif
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.c b/sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.c
new file mode 100644
index 0000000..ffa934a
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.c
@@ -0,0 +1,107 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_VNorm.h"
+#include "AKFS_Device.h"
+
+/*!
+ */
+int16 AKFS_VbNorm(
+ const int16 ndata, /*!< Size of raw vector buffer */
+ const AKFVEC vdata[], /*!< Raw vector buffer */
+ const int16 nbuf, /*!< Size of data to be buffered */
+ const AKFVEC* o, /*!< Offset */
+ const AKFVEC* s, /*!< Sensitivity */
+ const AKFLOAT tgt, /*!< Target sensitivity */
+ const int16 nvec, /*!< Size of normalized vector buffer */
+ AKFVEC vvec[] /*!< Normalized vector buffer */
+)
+{
+ int i;
+
+ /* size check */
+ if ((ndata <= 0) || (nvec <= 0) || (nbuf <= 0)) {
+ return AKFS_ERROR;
+ }
+ /* dependency check */
+ if ((nbuf < 1) || (ndata < nbuf) || (nvec < nbuf)) {
+ return AKFS_ERROR;
+ }
+ /* sensitivity check */
+ if ((s->u.x <= AKFS_EPSILON) ||
+ (s->u.y <= AKFS_EPSILON) ||
+ (s->u.z <= AKFS_EPSILON) ||
+ (tgt <= 0)) {
+ return AKFS_ERROR;
+ }
+
+ /* calculate and store data to buffer */
+ if (AKFS_BufShift(nvec, nbuf, vvec) != AKFS_SUCCESS) {
+ return AKFS_ERROR;
+ }
+ for (i=0; i<nbuf; i++) {
+ vvec[i].u.x = ((vdata[i].u.x - o->u.x) / (s->u.x) * (AKFLOAT)tgt);
+ vvec[i].u.y = ((vdata[i].u.y - o->u.y) / (s->u.y) * (AKFLOAT)tgt);
+ vvec[i].u.z = ((vdata[i].u.z - o->u.z) / (s->u.z) * (AKFLOAT)tgt);
+ }
+
+ return AKFS_SUCCESS;
+}
+
+/*!
+ */
+int16 AKFS_VbAve(
+ const int16 nvec, /*!< Size of normalized vector buffer */
+ const AKFVEC vvec[], /*!< Normalized vector buffer */
+ const int16 nave, /*!< Number of averaeg */
+ AKFVEC* vave /*!< Averaged vector */
+)
+{
+ int i;
+
+ /* arguments check */
+ if ((nave <= 0) || (nvec <= 0) || (nvec < nave)) {
+ return AKFS_ERROR;
+ }
+
+ /* calculate average */
+ vave->u.x = 0;
+ vave->u.y = 0;
+ vave->u.z = 0;
+ for (i=0; i<nave; i++) {
+ if ((vvec[i].u.x == AKFS_INIT_VALUE_F) ||
+ (vvec[i].u.y == AKFS_INIT_VALUE_F) ||
+ (vvec[i].u.z == AKFS_INIT_VALUE_F)) {
+ break;
+ }
+ vave->u.x += vvec[i].u.x;
+ vave->u.y += vvec[i].u.y;
+ vave->u.z += vvec[i].u.z;
+ }
+ if (i == 0) {
+ vave->u.x = 0;
+ vave->u.y = 0;
+ vave->u.z = 0;
+ } else {
+ vave->u.x /= i;
+ vave->u.y /= i;
+ vave->u.z /= i;
+ }
+ return AKFS_SUCCESS;
+}
+
+
diff --git a/sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.h b/sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.h
new file mode 100644
index 0000000..c3c9bed
--- /dev/null
+++ b/sensors/akmdfs/AKFS_APIs_8975/AKFS_VNorm.h
@@ -0,0 +1,46 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_VNORM_H
+#define AKFS_INC_VNORM_H
+
+#include "AKFS_Device.h"
+
+/***** Prototype of function **************************************************/
+AKLIB_C_API_START
+int16 AKFS_VbNorm(
+ const int16 ndata, /*!< Size of raw vector buffer */
+ const AKFVEC vdata[], /*!< Raw vector buffer */
+ const int16 nbuf, /*!< Size of data to be buffered */
+ const AKFVEC* o, /*!< Offset */
+ const AKFVEC* s, /*!< Sensitivity */
+ const AKFLOAT tgt, /*!< Target sensitivity */
+ const int16 nvec, /*!< Size of normalized vector buffer */
+ AKFVEC vvec[] /*!< Normalized vector buffer */
+);
+
+int16 AKFS_VbAve(
+ const int16 nvec, /*!< Size of normalized vector buffer */
+ const AKFVEC vvec[], /*!< Normalized vector buffer */
+ const int16 nave, /*!< Number of averaeg */
+ AKFVEC* vave /*!< Averaged vector */
+);
+
+AKLIB_C_API_END
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_CSpec.h b/sensors/akmdfs/AKFS_CSpec.h
new file mode 100644
index 0000000..380f06f
--- /dev/null
+++ b/sensors/akmdfs/AKFS_CSpec.h
@@ -0,0 +1,38 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_CSPEC_H
+#define AKFS_INC_CSPEC_H
+
+/*******************************************************************************
+ User defines parameters.
+ ******************************************************************************/
+/* Parameters for Average */
+/* The number of magnetic/acceleration data to be averaged. */
+#define CSPEC_HNAVE_D 4
+#define CSPEC_ANAVE_D 4
+#define CSPEC_HNAVE_V 8
+#define CSPEC_ANAVE_V 8
+
+#ifdef WIN32
+#define CSPEC_SETTING_FILE "akmdfs.txt"
+#else
+#define CSPEC_SETTING_FILE "/data/misc/akmdfs.txt"
+#endif
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_Common.h b/sensors/akmdfs/AKFS_Common.h
new file mode 100644
index 0000000..7780801
--- /dev/null
+++ b/sensors/akmdfs/AKFS_Common.h
@@ -0,0 +1,141 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_COMMON_H
+#define AKFS_INC_COMMON_H
+
+#ifdef WIN32
+#ifndef _WIN32_WINNT
+#define _WIN32_WINNT 0x0501
+#endif
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <conio.h>
+#include <stdarg.h>
+#include <crtdbg.h>
+#include "Android.h"
+
+#define DBG_LEVEL DBG_LEVEL4
+#define ENABLE_AKMDEBUG 1
+
+#else
+#include <stdio.h> /* frpintf */
+#include <stdlib.h> /* atoi */
+#include <string.h> /* memset */
+#include <unistd.h>
+#include <stdarg.h> /* va_list */
+#include <utils/Log.h> /* ALOGV */
+#include <errno.h> /* errno */
+
+#endif
+
+/*** Constant definition ******************************************************/
+#define AKM_TRUE 1 /*!< Represents true */
+#define AKM_FALSE 0 /*!< Represents false */
+#define AKM_SUCCESS 1 /*!< Represents success */
+#define AKM_FAIL 0 /*!< Represents fail */
+
+#define DBG_LEVEL0 0 /* Critical */
+#define DBG_LEVEL1 1 /* Notice */
+#define DBG_LEVEL2 2 /* Information */
+#define DBG_LEVEL3 3 /* Debug */
+#define DBG_LEVEL4 4 /* Verbose */
+
+#ifndef DBG_LEVEL
+#define DBG_LEVEL DBG_LEVEL0
+#endif
+
+#define DATA_AREA01 0x0001
+#define DATA_AREA02 0x0002
+#define DATA_AREA03 0x0004
+#define DATA_AREA04 0x0008
+#define DATA_AREA05 0x0010
+#define DATA_AREA06 0x0020
+#define DATA_AREA07 0x0040
+#define DATA_AREA08 0x0080
+#define DATA_AREA09 0x0100
+#define DATA_AREA10 0x0200
+#define DATA_AREA11 0x0400
+#define DATA_AREA12 0x0800
+#define DATA_AREA13 0x1000
+#define DATA_AREA14 0x2000
+#define DATA_AREA15 0x4000
+#define DATA_AREA16 0x8000
+
+
+/* Debug area definition */
+#define AKMDATA_DUMP DATA_AREA01 /*<! Dump data */
+#define AKMDATA_BDATA DATA_AREA02 /*<! BDATA */
+#define AKMDATA_MAG DATA_AREA03 /*<! Magnetic Field */
+#define AKMDATA_ACC DATA_AREA04 /*<! Accelerometer */
+#define AKMDATA_ORI DATA_AREA05 /*<! Orientation */
+#define AKMDATA_GETINTERVAL DATA_AREA06
+#define AKMDATA_LOOP DATA_AREA07
+#define AKMDATA_DRV DATA_AREA08
+
+#ifndef ENABLE_AKMDEBUG
+#define ENABLE_AKMDEBUG 0 /* Eanble debug output when it is 1. */
+#endif
+
+#define OPMODE_CONSOLE 0x01
+#define OPMODE_FST 0x02
+
+/***** Debug Level Output *************************************/
+#if ENABLE_AKMDEBUG
+#define AKMDEBUG(level, format, ...) \
+ (((level) <= DBG_LEVEL) \
+ ? (fprintf(stdout, (format), ##__VA_ARGS__)) \
+ : ((void)0))
+#else
+#define AKMDEBUG(level, format, ...)
+#endif
+
+/***** Dbg Zone Output ***************************************/
+#if ENABLE_AKMDEBUG
+#define AKMDATA(flag, format, ...) \
+ ((((int)flag) & g_dbgzone) \
+ ? (fprintf(stdout, (format), ##__VA_ARGS__)) \
+ : ((void)0))
+#else
+#define AKMDATA(flag, format, ...)
+#endif
+
+/***** Log output ********************************************/
+#ifdef AKM_LOG_ENABLE
+#define AKM_LOG(format, ...) ALOGD((format), ##__VA_ARGS__)
+#else
+#define AKM_LOG(format, ...)
+#endif
+
+/***** Error output *******************************************/
+#define AKMERROR \
+ ALOGE("%s:%d Error.", __FUNCTION__, __LINE__)
+
+#define AKMERROR_STR(api) \
+ ALOGE("%s:%d %s Error (%s).", \
+ __FUNCTION__, __LINE__, (api), strerror(errno))
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+
+#endif /* AKMD_INC_AKCOMMON_H */
+
diff --git a/sensors/akmdfs/AKFS_Compass.h b/sensors/akmdfs/AKFS_Compass.h
new file mode 100644
index 0000000..aa59285
--- /dev/null
+++ b/sensors/akmdfs/AKFS_Compass.h
@@ -0,0 +1,84 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_COMPASS_H
+#define AKFS_INC_COMPASS_H
+
+#include "AKFS_Common.h"
+#include "AKFS_CSpec.h"
+
+/****************************************/
+/* Include files for AK8975 library. */
+/****************************************/
+#include "AKFS_AK8975.h"
+#include "AKFS_Configure.h"
+#include "AKFS_AOC.h"
+#include "AKFS_Device.h"
+#include "AKFS_Direction.h"
+#include "AKFS_Math.h"
+#include "AKFS_VNorm.h"
+
+/*** Constant definition ******************************************************/
+
+/*** Type declaration *********************************************************/
+typedef struct _AKSENSOR_DATA{
+ AKFLOAT x;
+ AKFLOAT y;
+ AKFLOAT z;
+ int8 status;
+} AKSENSOR_DATA;
+
+/*! A parameter structure. */
+typedef struct _AK8975PRMS{
+ /* Variables for Decomp8975. */
+ AKFVEC mfv_hdata[AKFS_HDATA_SIZE];
+ uint8vec mi_asa;
+ uint8 mi_st;
+
+ /* Variables forAOC. */
+ AKFS_AOC_VAR m_aocv;
+
+ /* Variables for Magnetometer buffer. */
+ AKFVEC mfv_hvbuf[AKFS_HDATA_SIZE];
+ AKFVEC mfv_ho;
+ AKFVEC mfv_hs;
+ AKFS_PATNO m_hpat;
+
+ /* Variables for Accelerometer buffer. */
+ AKFVEC mfv_adata[AKFS_ADATA_SIZE];
+ AKFVEC mfv_avbuf[AKFS_ADATA_SIZE];
+ AKFVEC mfv_ao;
+ AKFVEC mfv_as;
+
+ /* Variables for Direction. */
+ int16 mi_hnaveD;
+ int16 mi_anaveD;
+ AKFLOAT mf_azimuth;
+ AKFLOAT mf_pitch;
+ AKFLOAT mf_roll;
+
+ /* Variables for vector output */
+ int16 mi_hnaveV;
+ int16 mi_anaveV;
+ AKFVEC mfv_hvec;
+ AKFVEC mfv_avec;
+ int16 mi_hstatus;
+
+} AK8975PRMS;
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_Disp.c b/sensors/akmdfs/AKFS_Disp.c
new file mode 100644
index 0000000..4e7c501
--- /dev/null
+++ b/sensors/akmdfs/AKFS_Disp.c
@@ -0,0 +1,89 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_Disp.h"
+#include "AKFS_Common.h"
+
+/*!
+ Print startup message to Android Log daemon.
+ */
+void Disp_StartMessage(void)
+{
+ ALOGI("AK8975 Daemon for Open Source v20120329.");
+ ALOGI("Debug: %s", ((ENABLE_AKMDEBUG)?("ON"):("OFF")));
+ ALOGI("Debug level: %d", DBG_LEVEL);
+}
+
+/*!
+ Print ending message to Android Log daemon.
+ */
+void Disp_EndMessage(int ret)
+{
+ ALOGI("AK8975 for Android end (%d).", ret);
+}
+
+/*!
+ Print result
+ */
+void Disp_Result(int buf[YPR_DATA_SIZE])
+{
+ AKMDEBUG(DBG_LEVEL1,
+ "Flag=%d\n", buf[0]);
+ AKMDEBUG(DBG_LEVEL1,
+ "Acc(%d):%8.2f, %8.2f, %8.2f\n",
+ buf[4], REVERT_ACC(buf[1]), REVERT_ACC(buf[2]), REVERT_ACC(buf[3]));
+ AKMDEBUG(DBG_LEVEL1,
+ "Mag(%d):%8.2f, %8.2f, %8.2f\n",
+ buf[8], REVERT_MAG(buf[5]), REVERT_MAG(buf[6]), REVERT_MAG(buf[7]));
+ AKMDEBUG(DBG_LEVEL1,
+ "Ori(%d)=%8.2f, %8.2f, %8.2f\n",
+ buf[8], REVERT_ORI(buf[9]), REVERT_ORI(buf[10]), REVERT_ORI(buf[11]));
+}
+
+/*!
+ Output main menu to stdout and wait for user input from stdin.
+ @return Selected mode.
+ */
+MODE Menu_Main(void)
+{
+ char msg[20];
+ memset(msg, 0, sizeof(msg));
+
+ AKMDEBUG(DBG_LEVEL1,
+ " -------------------- AK8975 Console Application -------------------- \n"
+ " 1. Start measurement. \n"
+ " 2. Self-test. \n"
+ " Q. Quit application. \n"
+ " --------------------------------------------------------------------- \n"
+ " Please select a number.\n"
+ " ---> ");
+ fgets(msg, 10, stdin);
+ AKMDEBUG(DBG_LEVEL1, "\n");
+
+ /* BUG : If 2-digits number is input, */
+ /* only the first character is compared. */
+ if (!strncmp(msg, "1", 1)) {
+ return MODE_Measure;
+ } else if (!strncmp(msg, "2", 1)) {
+ return MODE_SelfTest;
+ } else if (strncmp(msg, "Q", 1) == 0 || strncmp(msg, "q", 1) == 0) {
+ return MODE_Quit;
+ } else {
+ return MODE_ERROR;
+ }
+}
+
diff --git a/sensors/akmdfs/AKFS_Disp.h b/sensors/akmdfs/AKFS_Disp.h
new file mode 100644
index 0000000..4769e3c
--- /dev/null
+++ b/sensors/akmdfs/AKFS_Disp.h
@@ -0,0 +1,52 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_DISP_H
+#define AKFS_INC_DISP_H
+
+/* Include file for AK8975 library. */
+#include "AKFS_Compass.h"
+
+/*** Constant definition ******************************************************/
+#define REVERT_ACC(a) ((float)((a) * 9.8f / 720.0f))
+#define REVERT_MAG(m) ((float)((m) * 0.06f))
+#define REVERT_ORI(o) ((float)((o) / 64.0f))
+
+/*** Type declaration *********************************************************/
+
+/*! These defined types represents the current mode. */
+typedef enum _MODE {
+ MODE_ERROR, /*!< Error */
+ MODE_Measure, /*!< Measurement */
+ MODE_SelfTest, /*!< Self-test */
+ MODE_Quit /*!< Quit */
+} MODE;
+
+/*** Prototype of function ****************************************************/
+/*
+ Disp_ : Display messages.
+ Menu_ : Display menu (two or more selection) and wait for user input.
+ */
+
+void Disp_StartMessage(void);
+void Disp_EndMessage(int ret);
+void Disp_Result(int buf[YPR_DATA_SIZE]);
+
+MODE Menu_Main(void);
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_FileIO.c b/sensors/akmdfs/AKFS_FileIO.c
new file mode 100644
index 0000000..92c2ce9
--- /dev/null
+++ b/sensors/akmdfs/AKFS_FileIO.c
@@ -0,0 +1,130 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_FileIO.h"
+
+/*** Constant definition ******************************************************/
+#ifdef AKFS_PRECISION_DOUBLE
+#define AKFS_SCANF_FORMAT "%63s = %lf"
+#else
+#define AKFS_SCANF_FORMAT "%63s = %f"
+#endif
+#define AKFS_PRINTF_FORMAT "%s = %f\n"
+#define LOAD_BUF_SIZE 64
+
+/*!
+ Load parameters from file which is specified with #path. This function reads
+ data from a beginning of the file line by line, and check parameter name
+ sequentially. In otherword, this function depends on the order of eache
+ parameter described in the file.
+ @return If function fails, the return value is #AKM_FAIL. When function fails,
+ the output is undefined. Therefore, parameters which are possibly overwritten
+ by this function should be initialized again. If function succeeds, the
+ return value is #AKM_SUCCESS.
+ @param[out] prms A pointer to #AK8975PRMS structure. Loaded parameter is
+ stored to the member of this structure.
+ @param[in] path A path to the setting file.
+ */
+int16 AKFS_LoadParameters(AK8975PRMS * prms, const char* path)
+{
+ int16 ret;
+ char buf[LOAD_BUF_SIZE];
+ FILE *fp = NULL;
+
+ /* Open setting file for read. */
+ if ((fp = fopen(path, "r")) == NULL) {
+ AKMERROR_STR("fopen");
+ return AKM_FAIL;
+ }
+
+ ret = 1;
+
+ /* Load data to HO */
+ if (fscanf(fp, AKFS_SCANF_FORMAT, buf, &prms->mfv_ho.u.x) != 2) {
+ ret = 0;
+ } else {
+ if (strncmp(buf, "HO.x", sizeof(buf)) != 0) {
+ ret = 0;
+ }
+ }
+ if (fscanf(fp, AKFS_SCANF_FORMAT, buf, &prms->mfv_ho.u.y) != 2) {
+ ret = 0;
+ } else {
+ if (strncmp(buf, "HO.y", sizeof(buf)) != 0) {
+ ret = 0;
+ }
+ }
+ if (fscanf(fp, AKFS_SCANF_FORMAT, buf, &prms->mfv_ho.u.z) != 2) {
+ ret = 0;
+ } else {
+ if (strncmp(buf, "HO.z", sizeof(buf)) != 0) {
+ ret = 0;
+ }
+ }
+
+ if (fclose(fp) != 0) {
+ AKMERROR_STR("fclose");
+ ret = 0;
+ }
+
+ if (ret == 0) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ Save parameters to file which is specified with #path. This function saves
+ variables when the offsets of magnetic sensor estimated successfully.
+ @return If function fails, the return value is #AKM_FAIL. When function fails,
+ the parameter file may collapsed. Therefore, the parameters file should be
+ discarded. If function succeeds, the return value is #AKM_SUCCESS.
+ @param[out] prms A pointer to #AK8975PRMS structure. Member variables are
+ saved to the parameter file.
+ @param[in] path A path to the setting file.
+ */
+int16 AKFS_SaveParameters(AK8975PRMS *prms, const char* path)
+{
+ int16 ret = 1;
+ FILE *fp;
+
+ /*Open setting file for write. */
+ if ((fp = fopen(path, "w")) == NULL) {
+ AKMERROR_STR("fopen");
+ return AKM_FAIL;
+ }
+
+ /* Save data to HO */
+ if (fprintf(fp, AKFS_PRINTF_FORMAT, "HO.x", prms->mfv_ho.u.x) < 0) { ret = 0; }
+ if (fprintf(fp, AKFS_PRINTF_FORMAT, "HO.y", prms->mfv_ho.u.y) < 0) { ret = 0; }
+ if (fprintf(fp, AKFS_PRINTF_FORMAT, "HO.z", prms->mfv_ho.u.z) < 0) { ret = 0; }
+
+ if (fclose(fp) != 0) {
+ AKMERROR_STR("fclose");
+ ret = 0;
+ }
+
+ if (ret == 0) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ return AKM_SUCCESS;
+}
+
diff --git a/sensors/akmdfs/AKFS_FileIO.h b/sensors/akmdfs/AKFS_FileIO.h
new file mode 100644
index 0000000..62f6e77
--- /dev/null
+++ b/sensors/akmdfs/AKFS_FileIO.h
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_FILEIO_H
+#define AKFS_INC_FILEIO_H
+
+/* Common include files. */
+#include "AKFS_Common.h"
+
+/* Include file for AK8975 library. */
+#include "AKFS_Compass.h"
+
+/*** Constant definition ******************************************************/
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+int16 AKFS_LoadParameters(AK8975PRMS *prms, const char* path);
+
+int16 AKFS_SaveParameters(AK8975PRMS* prms, const char* path);
+
+#endif
+
diff --git a/sensors/akmdfs/AKFS_Measure.c b/sensors/akmdfs/AKFS_Measure.c
new file mode 100644
index 0000000..84c0843
--- /dev/null
+++ b/sensors/akmdfs/AKFS_Measure.c
@@ -0,0 +1,410 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#ifdef WIN32
+#include "AK8975_LinuxDriver.h"
+#else
+#include "AK8975Driver.h"
+#endif
+
+#include "AKFS_Measure.h"
+#include "AKFS_Disp.h"
+#include "AKFS_APIs.h"
+
+/*!
+ Read sensitivity adjustment data from fuse ROM.
+ @return If data are read successfully, the return value is #AKM_SUCCESS.
+ Otherwise the return value is #AKM_FAIL.
+ @param[out] regs The read ASA values. When this function succeeds, ASAX value
+ is saved in regs[0], ASAY is saved in regs[1], ASAZ is saved in regs[2].
+ */
+int16 AKFS_ReadAK8975FUSEROM(
+ uint8 regs[3]
+)
+{
+ /* Set to FUSE ROM access mode */
+ if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Read values. ASAX, ASAY, ASAZ */
+ if (AKD_RxData(AK8975_FUSE_ASAX, regs, 3) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Set to PowerDown mode */
+ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ AKMDEBUG(DBG_LEVEL2, "%s: asa(dec)=%d,%d,%d\n",
+ __FUNCTION__, regs[0], regs[1], regs[2]);
+
+ return AKM_SUCCESS;
+}
+
+/*!
+ Carry out self-test.
+ @return If this function succeeds, the return value is #AKM_SUCCESS.
+ Otherwise the return value is #AKM_FAIL.
+ */
+int16 AKFS_SelfTest(void)
+{
+ BYTE i2cData[SENSOR_DATA_SIZE];
+ BYTE asa[3];
+ AKFLOAT hdata[3];
+ int16 ret;
+
+ /* Set to FUSE ROM access mode */
+ if (AKD_SetMode(AK8975_MODE_FUSE_ACCESS) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Read values from ASAX to ASAZ */
+ if (AKD_RxData(AK8975_FUSE_ASAX, asa, 3) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Set to PowerDown mode */
+ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Set to self-test mode */
+ i2cData[0] = 0x40;
+ if (AKD_TxData(AK8975_REG_ASTC, i2cData, 1) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /* Set to Self-test mode */
+ if (AKD_SetMode(AK8975_MODE_SELF_TEST) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ /*
+ Wait for DRDY pin changes to HIGH.
+ Get measurement data from AK8975
+ */
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+
+ hdata[0] = AK8975_HDATA_CONVERTER(i2cData[2], i2cData[1], asa[0]);
+ hdata[1] = AK8975_HDATA_CONVERTER(i2cData[4], i2cData[3], asa[1]);
+ hdata[2] = AK8975_HDATA_CONVERTER(i2cData[6], i2cData[5], asa[2]);
+
+ /* Test */
+ ret = 1;
+ if ((hdata[0] < AK8975_SELFTEST_MIN_X) ||
+ (AK8975_SELFTEST_MAX_X < hdata[0])) {
+ ret = 0;
+ }
+ if ((hdata[1] < AK8975_SELFTEST_MIN_Y) ||
+ (AK8975_SELFTEST_MAX_Y < hdata[1])) {
+ ret = 0;
+ }
+ if ((hdata[2] < AK8975_SELFTEST_MIN_Z) ||
+ (AK8975_SELFTEST_MAX_Z < hdata[2])) {
+ ret = 0;
+ }
+
+ AKMDEBUG(DBG_LEVEL2, "Test(%s):%8.2f, %8.2f, %8.2f\n",
+ (ret ? "Success" : "fail"), hdata[0], hdata[1], hdata[2]);
+
+ if (ret) {
+ return AKM_SUCCESS;
+ } else {
+ return AKM_FAIL;
+ }
+}
+
+/*!
+ This function calculate the duration of sleep for maintaining
+ the loop keep the period.
+ This function calculates "minimum - (end - start)".
+ @return The result of above equation in nanosecond.
+ @param end The time of after execution.
+ @param start The time of before execution.
+ @param minimum Loop period of each execution.
+ */
+struct timespec AKFS_CalcSleep(
+ const struct timespec* end,
+ const struct timespec* start,
+ const int64_t minimum
+)
+{
+ int64_t endL;
+ int64_t startL;
+ int64_t diff;
+
+ struct timespec ret;
+
+ endL = (end->tv_sec * 1000000000) + end->tv_nsec;
+ startL = (start->tv_sec * 1000000000) + start->tv_nsec;
+ diff = minimum;
+
+ diff -= (endL - startL);
+
+ /* Don't allow negative value */
+ if (diff < 0) {
+ diff = 0;
+ }
+
+ /* Convert to timespec */
+ if (diff > 1000000000) {
+ ret.tv_sec = diff / 1000000000;
+ ret.tv_nsec = diff % 1000000000;
+ } else {
+ ret.tv_sec = 0;
+ ret.tv_nsec = diff;
+ }
+ return ret;
+}
+
+/*!
+ Get interval of each sensors from device driver.
+ @return If this function succeeds, the return value is #AKM_SUCCESS.
+ Otherwise the return value is #AKM_FAIL.
+ @param flag This variable indicates what sensor frequency is updated.
+ @param minimum This value show the minimum loop period in all sensors.
+ */
+int16 AKFS_GetInterval(
+ uint16* flag,
+ int64_t* minimum
+)
+{
+ /* Accelerometer, Magnetometer, Orientation */
+ /* Delay is in nano second unit. */
+ /* Negative value means the sensor is disabled.*/
+ int64_t delay[AKM_NUM_SENSORS];
+ int i;
+
+ if (AKD_GetDelay(delay) < 0) {
+ AKMERROR;
+ return AKM_FAIL;
+ }
+ AKMDATA(AKMDATA_GETINTERVAL,"delay[A,M,O]=%lld,%lld,%lld\n",
+ delay[0], delay[1], delay[2]);
+
+ /* update */
+ *minimum = 1000000000;
+ *flag = 0;
+ for (i=0; i<AKM_NUM_SENSORS; i++) {
+ /* Set flag */
+ if (delay[i] >= 0) {
+ *flag |= 1 << i;
+ if (*minimum > delay[i]) {
+ *minimum = delay[i];
+ }
+ }
+ }
+ return AKM_SUCCESS;
+}
+
+/*!
+ If this program run as console mode, measurement result will be displayed
+ on console terminal.
+ @return If this function succeeds, the return value is #AKM_SUCCESS.
+ Otherwise the return value is #AKM_FAIL.
+ */
+void AKFS_OutputResult(
+ const uint16 flag,
+ const AKSENSOR_DATA* acc,
+ const AKSENSOR_DATA* mag,
+ const AKSENSOR_DATA* ori
+)
+{
+ int buf[YPR_DATA_SIZE];
+
+ /* Store to buffer */
+ buf[0] = flag; /* Data flag */
+ buf[1] = CONVERT_ACC(acc->x); /* Ax */
+ buf[2] = CONVERT_ACC(acc->y); /* Ay */
+ buf[3] = CONVERT_ACC(acc->z); /* Az */
+ buf[4] = acc->status; /* Acc status */
+ buf[5] = CONVERT_MAG(mag->x); /* Mx */
+ buf[6] = CONVERT_MAG(mag->y); /* My */
+ buf[7] = CONVERT_MAG(mag->z); /* Mz */
+ buf[8] = mag->status; /* Mag status */
+ buf[9] = CONVERT_ORI(ori->x); /* yaw */
+ buf[10] = CONVERT_ORI(ori->y); /* pitch */
+ buf[11] = CONVERT_ORI(ori->z); /* roll */
+
+ if (g_opmode & OPMODE_CONSOLE) {
+ /* Console mode */
+ Disp_Result(buf);
+ }
+
+ /* Set result to driver */
+ AKD_SetYPR(buf);
+}
+
+/*!
+ This is the main routine of measurement.
+ */
+void AKFS_MeasureLoop(void)
+{
+ BYTE i2cData[SENSOR_DATA_SIZE]; /* ST1 ~ ST2 */
+ int16 mag[3];
+ int16 mstat;
+ int16 acc[3];
+ struct timespec tsstart= {0, 0};
+ struct timespec tsend = {0, 0};
+ struct timespec doze;
+ int64_t minimum;
+ uint16 flag;
+ AKSENSOR_DATA sv_acc;
+ AKSENSOR_DATA sv_mag;
+ AKSENSOR_DATA sv_ori;
+ AKFLOAT tmpx, tmpy, tmpz;
+ int16 tmp_accuracy;
+
+ minimum = -1;
+
+#ifdef WIN32
+ clock_init_time();
+#endif
+
+ /* Initialize library functions and device */
+ if (AKFS_Start(CSPEC_SETTING_FILE) != AKM_SUCCESS) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+
+ while (g_stopRequest != AKM_TRUE) {
+ /* Beginning time */
+ if (clock_gettime(CLOCK_MONOTONIC, &tsstart) < 0) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+
+ /* Get interval */
+ if (AKFS_GetInterval(&flag, &minimum) != AKM_SUCCESS) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+
+ if ((flag & ACC_DATA_READY) || (flag & ORI_DATA_READY)) {
+ /* Get accelerometer */
+ if (AKD_GetAccelerationData(acc) != AKD_SUCCESS) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+
+ /* Calculate accelerometer vector */
+ if (AKFS_Get_ACCELEROMETER(acc, 0, &tmpx, &tmpy, &tmpz, &tmp_accuracy) == AKM_SUCCESS) {
+ sv_acc.x = tmpx;
+ sv_acc.y = tmpy;
+ sv_acc.z = tmpz;
+ sv_acc.status = tmp_accuracy;
+ } else {
+ flag &= ~ACC_DATA_READY;
+ flag &= ~ORI_DATA_READY;
+ }
+ }
+
+ if ((flag & MAG_DATA_READY) || (flag & ORI_DATA_READY)) {
+ /* Set to measurement mode */
+ if (AKD_SetMode(AK8975_MODE_SNG_MEASURE) != AKD_SUCCESS) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+
+ /* Wait for DRDY and get data from device */
+ if (AKD_GetMagneticData(i2cData) != AKD_SUCCESS) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+ /* raw data to x,y,z value */
+ mag[0] = (int)((int16_t)(i2cData[2]<<8)+((int16_t)i2cData[1]));
+ mag[1] = (int)((int16_t)(i2cData[4]<<8)+((int16_t)i2cData[3]));
+ mag[2] = (int)((int16_t)(i2cData[6]<<8)+((int16_t)i2cData[5]));
+ mstat = i2cData[0] | i2cData[7];
+
+ AKMDATA(AKMDATA_BDATA,
+ "bData=%02X,%02X,%02X,%02X,%02X,%02X,%02X,%02X\n",
+ i2cData[0], i2cData[1], i2cData[2], i2cData[3],
+ i2cData[4], i2cData[5], i2cData[6], i2cData[7]);
+
+ /* Calculate magnetic field vector */
+ if (AKFS_Get_MAGNETIC_FIELD(mag, mstat, &tmpx, &tmpy, &tmpz, &tmp_accuracy) == AKM_SUCCESS) {
+ sv_mag.x = tmpx;
+ sv_mag.y = tmpy;
+ sv_mag.z = tmpz;
+ sv_mag.status = tmp_accuracy;
+ } else {
+ flag &= ~MAG_DATA_READY;
+ flag &= ~ORI_DATA_READY;
+ }
+ }
+
+ if (flag & ORI_DATA_READY) {
+ if (AKFS_Get_ORIENTATION(&tmpx, &tmpy, &tmpz, &tmp_accuracy) == AKM_SUCCESS) {
+ sv_ori.x = tmpx;
+ sv_ori.y = tmpy;
+ sv_ori.z = tmpz;
+ sv_ori.status = tmp_accuracy;
+ } else {
+ flag &= ~ORI_DATA_READY;
+ }
+ }
+
+ /* Output result */
+ AKFS_OutputResult(flag, &sv_acc, &sv_mag, &sv_ori);
+
+ /* Ending time */
+ if (clock_gettime(CLOCK_MONOTONIC, &tsend) < 0) {
+ AKMERROR;
+ goto MEASURE_END;
+ }
+
+ /* Calculate duration */
+ doze = AKFS_CalcSleep(&tsend, &tsstart, minimum);
+ AKMDATA(AKMDATA_LOOP, "Sleep: %6.2f msec\n", (doze.tv_nsec/1000000.0f));
+ nanosleep(&doze, NULL);
+
+#ifdef WIN32
+ if (_kbhit()) {
+ _getch();
+ break;
+ }
+#endif
+ }
+
+MEASURE_END:
+ /* Set to PowerDown mode */
+ if (AKD_SetMode(AK8975_MODE_POWERDOWN) != AKD_SUCCESS) {
+ AKMERROR;
+ return;
+ }
+
+ /* Save parameters */
+ if (AKFS_Stop(CSPEC_SETTING_FILE) != AKM_SUCCESS) {
+ AKMERROR;
+ }
+}
+
+
diff --git a/sensors/akmdfs/AKFS_Measure.h b/sensors/akmdfs/AKFS_Measure.h
new file mode 100644
index 0000000..d156b95
--- /dev/null
+++ b/sensors/akmdfs/AKFS_Measure.h
@@ -0,0 +1,70 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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 AKFS_INC_MEASURE_H
+#define AKFS_INC_MEASURE_H
+
+/* Include files for AK8975 library. */
+#include "AKFS_Compass.h"
+
+/*** Constant definition ******************************************************/
+#define AK8975_SELFTEST_MIN_X -100
+#define AK8975_SELFTEST_MAX_X 100
+
+#define AK8975_SELFTEST_MIN_Y -100
+#define AK8975_SELFTEST_MAX_Y 100
+
+#define AK8975_SELFTEST_MIN_Z -1000
+#define AK8975_SELFTEST_MAX_Z -300
+
+#define CONVERT_ACC(a) ((int)((a) * 720 / 9.8f))
+#define CONVERT_MAG(m) ((int)((m) / 0.06f))
+#define CONVERT_ORI(o) ((int)((o) * 64))
+
+/*** Type declaration *********************************************************/
+
+/*** Global variables *********************************************************/
+
+/*** Prototype of function ****************************************************/
+int16 AKFS_ReadAK8975FUSEROM(
+ uint8 regs[3]
+);
+
+int16 AKFS_SelfTest(void);
+
+struct timespec AKFS_CalcSleep(
+ const struct timespec* end,
+ const struct timespec* start,
+ const int64_t minimum
+);
+
+int16 AKFS_GetInterval(
+ uint16* flag,
+ int64_t* minimum
+);
+
+void AKFS_OutputResult(
+ const uint16 flag,
+ const AKSENSOR_DATA* acc,
+ const AKSENSOR_DATA* mag,
+ const AKSENSOR_DATA* ori
+);
+
+void AKFS_MeasureLoop(void);
+
+#endif
+
diff --git a/sensors/akmdfs/NOTICE b/sensors/akmdfs/NOTICE
new file mode 100644
index 0000000..d645695
--- /dev/null
+++ b/sensors/akmdfs/NOTICE
@@ -0,0 +1,202 @@
+
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright [yyyy] [name of copyright owner]
+
+ 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.
diff --git a/sensors/akmdfs/Version.txt b/sensors/akmdfs/Version.txt
new file mode 100644
index 0000000..3d56b30
--- /dev/null
+++ b/sensors/akmdfs/Version.txt
@@ -0,0 +1,31 @@
+Version
+ * Console Version 20120329
+ 570 AK8975Driver.c
+ 496 AK8975Driver.h
+ 579 AKFS_APIs.c
+ 572 AKFS_APIs.h
+ 580 AKFS_APIs_8975/AKFS_AK8975.c
+ 580 AKFS_APIs_8975/AKFS_AK8975.h
+ 580 AKFS_APIs_8975/AKFS_AOC.c
+ 580 AKFS_APIs_8975/AKFS_AOC.h
+ 580 AKFS_APIs_8975/AKFS_Configure.h
+ 580 AKFS_APIs_8975/AKFS_Device.c
+ 580 AKFS_APIs_8975/AKFS_Device.h
+ 580 AKFS_APIs_8975/AKFS_Direction.c
+ 580 AKFS_APIs_8975/AKFS_Direction.h
+ 580 AKFS_APIs_8975/AKFS_Math.h
+ 580 AKFS_APIs_8975/AKFS_VNorm.c
+ 580 AKFS_APIs_8975/AKFS_VNorm.h
+ 568 AKFS_CSpec.h
+ 573 AKFS_Common.h
+ 572 AKFS_Compass.h
+ 579 AKFS_Disp.c
+ 568 AKFS_Disp.h
+ 568 AKFS_FileIO.c
+ 549 AKFS_FileIO.h
+ 573 AKFS_Measure.c
+ 568 AKFS_Measure.h
+ 574 Android.mk
+ 575 NOTICE
+ 579 main.c
+
diff --git a/sensors/akmdfs/main.c b/sensors/akmdfs/main.c
new file mode 100644
index 0000000..a3df0bc
--- /dev/null
+++ b/sensors/akmdfs/main.c
@@ -0,0 +1,293 @@
+/******************************************************************************
+ *
+ * Copyright (C) 2012 Asahi Kasei Microdevices Corporation, Japan
+ *
+ * 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.
+ *
+ ******************************************************************************/
+#include "AKFS_Common.h"
+#include "AKFS_Compass.h"
+#include "AKFS_Disp.h"
+#include "AKFS_FileIO.h"
+#include "AKFS_Measure.h"
+#include "AKFS_APIs.h"
+
+#ifndef WIN32
+#include <sched.h>
+#include <pthread.h>
+#include <linux/input.h>
+#endif
+
+#define ERROR_INITDEVICE (-1)
+#define ERROR_OPTPARSE (-2)
+#define ERROR_SELF_TEST (-3)
+#define ERROR_READ_FUSE (-4)
+#define ERROR_INIT (-5)
+#define ERROR_GETOPEN_STAT (-6)
+#define ERROR_STARTCLONE (-7)
+#define ERROR_GETCLOSE_STAT (-8)
+
+/* Global variable. See AKFS_Common.h file. */
+int g_stopRequest = 0;
+int g_opmode = 0;
+int g_dbgzone = 0;
+int g_mainQuit = AKD_FALSE;
+
+/* Static variable. */
+static pthread_t s_thread; /*!< Thread handle */
+
+/*!
+ A thread function which is raised when measurement is started.
+ @param[in] args This parameter is not used currently.
+ */
+static void* thread_main(void* args)
+{
+ AKFS_MeasureLoop();
+ return ((void*)0);
+}
+
+/*!
+ Signal handler. This should be used only in DEBUG mode.
+ @param[in] sig Event
+ */
+static void signal_handler(int sig)
+{
+ if (sig == SIGINT) {
+ ALOGE("SIGINT signal");
+ g_stopRequest = 1;
+ g_mainQuit = AKD_TRUE;
+ }
+}
+
+/*!
+ Starts new thread.
+ @return If this function succeeds, the return value is 1. Otherwise,
+ the return value is 0.
+ */
+static int startClone(void)
+{
+ pthread_attr_t attr;
+
+ pthread_attr_init(&attr);
+ g_stopRequest = 0;
+ if (pthread_create(&s_thread, &attr, thread_main, NULL) == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/*!
+ This function parse the option.
+ @retval 1 Parse succeeds.
+ @retval 0 Parse failed.
+ @param[in] argc Argument count
+ @param[in] argv Argument vector
+ @param[out] layout_patno
+ */
+int OptParse(
+ int argc,
+ char* argv[],
+ AKFS_PATNO* layout_patno)
+{
+#ifdef WIN32
+ /* Static */
+#if defined(AKFS_WIN32_PAT1)
+ *layout_patno = PAT1;
+#elif defined(AKFS_WIN32_PAT2)
+ *layout_patno = PAT2;
+#elif defined(AKFS_WIN32_PAT3)
+ *layout_patno = PAT3;
+#elif defined(AKFS_WIN32_PAT4)
+ *layout_patno = PAT4;
+#elif defined(AKFS_WIN32_PAT5)
+ *layout_patno = PAT5;
+#else
+ *layout_patno = PAT1;
+#endif
+ g_opmode = OPMODE_CONSOLE;
+ /*g_opmode = 0;*/
+ g_dbgzone = AKMDATA_LOOP | AKMDATA_TEST;
+#else
+ int opt;
+ char optVal;
+
+ *layout_patno = PAT_INVALID;
+
+ while ((opt = getopt(argc, argv, "sm:z:")) != -1) {
+ switch(opt){
+ case 'm':
+ optVal = (char)(optarg[0] - '0');
+ if ((PAT1 <= optVal) && (optVal <= PAT8)) {
+ *layout_patno = (AKFS_PATNO)optVal;
+ AKMDEBUG(DBG_LEVEL2, "%s: Layout=%d\n", __FUNCTION__, optVal);
+ }
+ break;
+ case 's':
+ g_opmode |= OPMODE_CONSOLE;
+ break;
+ case 'z':
+ /* If error detected, hopefully 0 is returned. */
+ errno = 0;
+ g_dbgzone = (int)strtol(optarg, (char**)NULL, 0);
+ AKMDEBUG(DBG_LEVEL2, "%s: Dbg Zone=%d\n", __FUNCTION__, g_dbgzone);
+ break;
+ default:
+ ALOGE("%s: Invalid argument", argv[0]);
+ return 0;
+ }
+ }
+
+ /* If layout is not specified with argument, get parameter from driver */
+ if (*layout_patno == PAT_INVALID) {
+ int16_t n;
+ if (AKD_GetLayout(&n) == AKM_SUCCESS) {
+ if ((PAT1 <= n) && (n <= PAT8)) {
+ *layout_patno = (AKFS_PATNO)n;
+ }
+ }
+ }
+ /* Error */
+ if (*layout_patno == PAT_INVALID) {
+ ALOGE("No layout is specified.");
+ return 0;
+ }
+#endif
+
+ return 1;
+}
+
+void ConsoleMode(void)
+{
+ /*** Console Mode *********************************************/
+ while (AKD_TRUE) {
+ /* Select operation */
+ switch (Menu_Main()) {
+ case MODE_SelfTest:
+ AKFS_SelfTest();
+ break;
+ case MODE_Measure:
+ /* Reset flag */
+ g_stopRequest = 0;
+ /* Measurement routine */
+ AKFS_MeasureLoop();
+ break;
+
+ case MODE_Quit:
+ return;
+
+ default:
+ AKMDEBUG(DBG_LEVEL0, "Unknown operation mode.\n");
+ break;
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int retValue = 0;
+ AKFS_PATNO pat;
+ uint8 regs[3];
+
+ /* Show the version info of this software. */
+ Disp_StartMessage();
+
+#if ENABLE_AKMDEBUG
+ /* Register signal handler */
+ signal(SIGINT, signal_handler);
+#endif
+
+ /* Open device driver */
+ if(AKD_InitDevice() != AKD_SUCCESS) {
+ retValue = ERROR_INITDEVICE;
+ goto MAIN_QUIT;
+ }
+
+ /* Parse command-line options */
+ /* This function calls device driver function to get layout */
+ if (OptParse(argc, argv, &pat) == 0) {
+ retValue = ERROR_OPTPARSE;
+ goto MAIN_QUIT;
+ }
+
+ /* Self Test */
+ if (g_opmode & OPMODE_FST){
+ if (AKFS_SelfTest() != AKD_SUCCESS) {
+ retValue = ERROR_SELF_TEST;
+ goto MAIN_QUIT;
+ }
+ }
+
+ /* OK, then start */
+ if (AKFS_ReadAK8975FUSEROM(regs) != AKM_SUCCESS) {
+ retValue = ERROR_READ_FUSE;
+ goto MAIN_QUIT;
+ }
+
+ /* Initialize library. */
+ if (AKFS_Init(pat, regs) != AKM_SUCCESS) {
+ retValue = ERROR_INIT;
+ goto MAIN_QUIT;
+ }
+
+ /* Start console mode */
+ if (g_opmode & OPMODE_CONSOLE) {
+ ConsoleMode();
+ goto MAIN_QUIT;
+ }
+
+ /*** Start Daemon ********************************************/
+ while (g_mainQuit == AKD_FALSE) {
+ int st = 0;
+ /* Wait until device driver is opened. */
+ if (AKD_GetOpenStatus(&st) != AKD_SUCCESS) {
+ retValue = ERROR_GETOPEN_STAT;
+ goto MAIN_QUIT;
+ }
+ if (st == 0) {
+ ALOGI("Suspended.");
+ } else {
+ ALOGI("Compass Opened.");
+ /* Reset flag */
+ g_stopRequest = 0;
+ /* Start measurement thread. */
+ if (startClone() == 0) {
+ retValue = ERROR_STARTCLONE;
+ goto MAIN_QUIT;
+ }
+
+ /* Wait until device driver is closed. */
+ if (AKD_GetCloseStatus(&st) != AKD_SUCCESS) {
+ retValue = ERROR_GETCLOSE_STAT;
+ g_mainQuit = AKD_TRUE;
+ }
+ /* Wait thread completion. */
+ g_stopRequest = 1;
+ pthread_join(s_thread, NULL);
+ ALOGI("Compass Closed.");
+ }
+ }
+
+MAIN_QUIT:
+
+ /* Release library */
+ AKFS_Release();
+ /* Close device driver. */
+ AKD_DeinitDevice();
+ /* Show the last message. */
+ Disp_EndMessage(retValue);
+
+ return retValue;
+}
+
+