diff options
Diffstat (limited to 'mlsdk/platform/linux/mlsl_linux_mpu.c')
-rw-r--r-- | mlsdk/platform/linux/mlsl_linux_mpu.c | 497 |
1 files changed, 497 insertions, 0 deletions
diff --git a/mlsdk/platform/linux/mlsl_linux_mpu.c b/mlsdk/platform/linux/mlsl_linux_mpu.c new file mode 100644 index 0000000..29930b3 --- /dev/null +++ b/mlsdk/platform/linux/mlsl_linux_mpu.c @@ -0,0 +1,497 @@ +/* + $License: + Copyright 2011 InvenSense, Inc. + + 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. + $ + */ + +/****************************************************************************** + * $Id: mlsl_linux_mpu.c 5653 2011-06-16 21:06:55Z nroyer $ + *****************************************************************************/ + +/** + * @defgroup MLSL (Motion Library - Serial Layer) + * @brief The Motion Library System Layer provides the Motion Library the + * interface to the system functions. + * + * @{ + * @file mlsl_linux_mpu.c + * @brief The Motion Library System Layer. + * + */ + +/* ------------------ */ +/* - Include Files. - */ +/* ------------------ */ +#include <stdio.h> +#include <sys/ioctl.h> +#include <stdlib.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <linux/fs.h> +#include <linux/i2c.h> +#include <string.h> +#include <signal.h> +#include <time.h> + +#include "mpu.h" +#if defined CONFIG_MPU_SENSORS_MPU6050A2 +# include "mpu6050a2.h" +#elif defined CONFIG_MPU_SENSORS_MPU6050B1 +# include "mpu6050b1.h" +#elif defined CONFIG_MPU_SENSORS_MPU3050 +# include "mpu3050.h" +#else +#error Invalid or undefined CONFIG_MPU_SENSORS_MPUxxxx +#endif + +#include "mlsl.h" +#include "mlos.h" +#include "mlmath.h" +#include "mlinclude.h" + +#define MLCAL_ID (0x0A0B0C0DL) +#define MLCAL_FILE "/data/cal.bin" +#define MLCFG_ID (0x01020304L) +#define MLCFG_FILE "/data/cfg.bin" + +#include <log.h> +#undef MPL_LOG_TAG +#define MPL_LOG_TAG "MPL-mlsl" + +#ifndef I2CDEV +#define I2CDEV "/dev/mpu" +#endif + +#define SERIAL_FULL_DEBUG (0) + +/* --------------- */ +/* - Prototypes. - */ +/* --------------- */ + +/* ----------------------- */ +/* - Function Pointers. - */ +/* ----------------------- */ + +/* --------------------------- */ +/* - Global and Static vars. - */ +/* --------------------------- */ + +/* ---------------- */ +/* - Definitions. - */ +/* ---------------- */ + +inv_error_t inv_serial_read_cfg(unsigned char *cfg, unsigned int len) +{ + FILE *fp; + int bytesRead; + + fp = fopen(MLCFG_FILE, "rb"); + if (fp == NULL) { + MPL_LOGE("Unable to open \"%s\" for read\n", MLCFG_FILE); + return INV_ERROR_FILE_OPEN; + } + bytesRead = fread(cfg, 1, len, fp); + if (bytesRead != len) { + MPL_LOGE("bytes read (%d) don't match requested length (%d)\n", + bytesRead, len); + return INV_ERROR_FILE_READ; + } + fclose(fp); + + if (((unsigned int)cfg[0] << 24 | cfg[1] << 16 | cfg[2] << 8 | cfg[3]) + != MLCFG_ID) { + return INV_ERROR_ASSERTION_FAILURE; + } + + return INV_SUCCESS; +} + +inv_error_t inv_serial_write_cfg(unsigned char *cfg, unsigned int len) +{ + FILE *fp; + int bytesWritten; + unsigned char cfgId[4]; + + fp = fopen(MLCFG_FILE,"wb"); + if (fp == NULL) { + MPL_LOGE("Unable to open \"%s\" for write\n", MLCFG_FILE); + return INV_ERROR_FILE_OPEN; + } + + cfgId[0] = (unsigned char)(MLCFG_ID >> 24); + cfgId[1] = (unsigned char)(MLCFG_ID >> 16); + cfgId[2] = (unsigned char)(MLCFG_ID >> 8); + cfgId[3] = (unsigned char)(MLCFG_ID); + bytesWritten = fwrite(cfgId, 1, 4, fp); + if (bytesWritten != 4) { + MPL_LOGE("CFG ID could not be written on file\n"); + return INV_ERROR_FILE_WRITE; + } + + bytesWritten = fwrite(cfg, 1, len, fp); + if (bytesWritten != len) { + MPL_LOGE("bytes write (%d) don't match requested length (%d)\n", + bytesWritten, len); + return INV_ERROR_FILE_WRITE; + } + + fclose(fp); + + return INV_SUCCESS; +} + +inv_error_t inv_serial_read_cal(unsigned char *cal, unsigned int len) +{ + FILE *fp; + int bytesRead; + inv_error_t result = INV_SUCCESS; + + fp = fopen(MLCAL_FILE,"rb"); + if (fp == NULL) { + MPL_LOGE("Cannot open file \"%s\" for read\n", MLCAL_FILE); + return INV_ERROR_FILE_OPEN; + } + bytesRead = fread(cal, 1, len, fp); + if (bytesRead != len) { + MPL_LOGE("bytes read (%d) don't match requested length (%d)\n", + bytesRead, len); + result = INV_ERROR_FILE_READ; + goto read_cal_end; + } + + /* MLCAL_ID not used + if (((unsigned int)cal[0] << 24 | cal[1] << 16 | cal[2] << 8 | cal[3]) + != MLCAL_ID) { + result = INV_ERROR_ASSERTION_FAILURE; + goto read_cal_end; + } + */ +read_cal_end: + fclose(fp); + return result; +} + +inv_error_t inv_serial_write_cal(unsigned char *cal, unsigned int len) +{ + FILE *fp; + int bytesWritten; + inv_error_t result = INV_SUCCESS; + + fp = fopen(MLCAL_FILE,"wb"); + if (fp == NULL) { + MPL_LOGE("Cannot open file \"%s\" for write\n", MLCAL_FILE); + return INV_ERROR_FILE_OPEN; + } + bytesWritten = fwrite(cal, 1, len, fp); + if (bytesWritten != len) { + MPL_LOGE("bytes written (%d) don't match requested length (%d)\n", + bytesWritten, len); + result = INV_ERROR_FILE_WRITE; + } + fclose(fp); + return result; +} + +inv_error_t inv_serial_get_cal_length(unsigned int *len) +{ + FILE *calFile; + *len = 0; + + calFile = fopen(MLCAL_FILE, "rb"); + if (calFile == NULL) { + MPL_LOGE("Cannot open file \"%s\" for read\n", MLCAL_FILE); + return INV_ERROR_FILE_OPEN; + } + + *len += (unsigned char)fgetc(calFile) << 24; + *len += (unsigned char)fgetc(calFile) << 16; + *len += (unsigned char)fgetc(calFile) << 8; + *len += (unsigned char)fgetc(calFile); + + fclose(calFile); + + if (*len <= 0) + return INV_ERROR_FILE_READ; + + return INV_SUCCESS; +} + +inv_error_t inv_serial_open(char const *port, void **sl_handle) +{ + INVENSENSE_FUNC_START; + + if (NULL == port) { + port = I2CDEV; + } + *sl_handle = (void*) open(port, O_RDWR); + if(sl_handle < 0) { + /* ERROR HANDLING; you can check errno to see what went wrong */ + MPL_LOGE("inv_serial_open\n"); + MPL_LOGE("I2C Error %d: Cannot open Adapter %s\n", errno, port); + return INV_ERROR_SERIAL_OPEN_ERROR; + } else { + MPL_LOGI("inv_serial_open: %s\n", port); + } + + return INV_SUCCESS; +} + +inv_error_t inv_serial_close(void *sl_handle) +{ + INVENSENSE_FUNC_START; + + close((int)sl_handle); + + return INV_SUCCESS; +} + +inv_error_t inv_serial_reset(void *sl_handle) +{ + return INV_ERROR_FEATURE_NOT_IMPLEMENTED; +} + +inv_error_t inv_serial_single_write(void *sl_handle, + unsigned char slaveAddr, + unsigned char registerAddr, + unsigned char data) +{ + unsigned char buf[2]; + buf[0] = registerAddr; + buf[1] = data; + return inv_serial_write(sl_handle, slaveAddr, 2, buf); +} + +inv_error_t inv_serial_write(void *sl_handle, + unsigned char slaveAddr, + unsigned short length, + unsigned char const *data) +{ + INVENSENSE_FUNC_START; + struct mpu_read_write msg; + inv_error_t result; + + if (NULL == data) { + return INV_ERROR_INVALID_PARAMETER; + } + + msg.address = 0; /* not used */ + msg.length = length; + msg.data = (unsigned char*)data; + + if ((result = ioctl((int)sl_handle, MPU_WRITE, &msg))) { + MPL_LOGE("I2C Error: could not write: R:%02x L:%d %d \n", + data[0], length, result); + return result; + } else if (SERIAL_FULL_DEBUG) { + char data_buff[4096] = ""; + char strchar[3]; + int ii; + for (ii = 0; ii < length; ii++) { + snprintf(strchar, sizeof(strchar), "%02x", data[0]); + strncat(data_buff, strchar, sizeof(data_buff)); + } + MPL_LOGI("I2C Write Success %02x %02x: %s \n", + data[0], length, data_buff); + } + + return INV_SUCCESS; +} + +inv_error_t inv_serial_read(void *sl_handle, + unsigned char slaveAddr, + unsigned char registerAddr, + unsigned short length, + unsigned char *data) +{ + INVENSENSE_FUNC_START; + int result = INV_SUCCESS; + struct mpu_read_write msg; + + if (NULL == data) { + return INV_ERROR_INVALID_PARAMETER; + } + + msg.address = registerAddr; + msg.length = length; + msg.data = data; + + result = ioctl((int)sl_handle, MPU_READ, &msg); + + if (result != INV_SUCCESS) { + MPL_LOGE("I2C Error %08x: could not read: R:%02x L:%d\n", + result, registerAddr, length); + result = INV_ERROR_SERIAL_READ; + } else if (SERIAL_FULL_DEBUG) { + char data_buff[4096] = ""; + char strchar[3]; + int ii; + for (ii = 0; ii < length; ii++) { + snprintf(strchar, sizeof(strchar), "%02x", data[0]); + strncat(data_buff, strchar, sizeof(data_buff)); + } + MPL_LOGI("I2C Read Success %02x %02x: %s \n", + registerAddr, length, data_buff); + } + + return (inv_error_t) result; +} + +inv_error_t inv_serial_write_mem(void *sl_handle, + unsigned char mpu_addr, + unsigned short memAddr, + unsigned short length, + const unsigned char *data) +{ + INVENSENSE_FUNC_START; + struct mpu_read_write msg; + int result; + + msg.address = memAddr; + msg.length = length; + msg.data = (unsigned char *)data; + + result = ioctl((int)sl_handle, MPU_WRITE_MEM, &msg); + if (result) { + LOG_RESULT_LOCATION(result); + return result; + } else if (SERIAL_FULL_DEBUG) { + char data_buff[4096] = ""; + char strchar[3]; + int ii; + for (ii = 0; ii < length; ii++) { + snprintf(strchar, sizeof(strchar), "%02x", data[0]); + strncat(data_buff, strchar, sizeof(data_buff)); + } + MPL_LOGI("I2C WriteMem Success %04x %04x: %s \n", + memAddr, length, data_buff); + } + return INV_SUCCESS; +} + +inv_error_t inv_serial_read_mem(void *sl_handle, + unsigned char mpu_addr, + unsigned short memAddr, + unsigned short length, + unsigned char *data) +{ + INVENSENSE_FUNC_START; + struct mpu_read_write msg; + int result; + + if (NULL == data) { + return INV_ERROR_INVALID_PARAMETER; + } + + msg.address = memAddr; + msg.length = length; + msg.data = data; + + result = ioctl((int)sl_handle, MPU_READ_MEM, &msg); + if (result != INV_SUCCESS) { + MPL_LOGE("I2C Error %08x: could not read memory: A:%04x L:%d\n", + result, memAddr, length); + return INV_ERROR_SERIAL_READ; + } else if (SERIAL_FULL_DEBUG) { + char data_buff[4096] = ""; + char strchar[3]; + int ii; + for (ii = 0; ii < length; ii++) { + snprintf(strchar, sizeof(strchar), "%02x", data[0]); + strncat(data_buff, strchar, sizeof(data_buff)); + } + MPL_LOGI("I2C ReadMem Success %04x %04x: %s\n", + memAddr, length, data_buff); + } + return INV_SUCCESS; +} + +inv_error_t inv_serial_write_fifo(void *sl_handle, + unsigned char mpu_addr, + unsigned short length, + const unsigned char *data) +{ + INVENSENSE_FUNC_START; + struct mpu_read_write msg; + int result; + + if (NULL == data) { + return INV_ERROR_INVALID_PARAMETER; + } + + msg.address = 0; /* Not used */ + msg.length = length; + msg.data = (unsigned char *)data; + + result = ioctl((int)sl_handle, MPU_WRITE_FIFO, &msg); + if (result != INV_SUCCESS) { + MPL_LOGE("I2C Error: could not write fifo: %02x %02x\n", + MPUREG_FIFO_R_W, length); + return INV_ERROR_SERIAL_WRITE; + } else if (SERIAL_FULL_DEBUG) { + char data_buff[4096] = ""; + char strchar[3]; + int ii; + for (ii = 0; ii < length; ii++) { + snprintf(strchar, sizeof(strchar), "%02x", data[0]); + strncat(data_buff, strchar, sizeof(data_buff)); + } + MPL_LOGI("I2C Write Success %02x %02x: %s\n", + MPUREG_FIFO_R_W, length, data_buff); + } + return (inv_error_t) result; +} + +inv_error_t inv_serial_read_fifo(void *sl_handle, + unsigned char mpu_addr, + unsigned short length, + unsigned char *data) +{ + INVENSENSE_FUNC_START; + struct mpu_read_write msg; + int result; + + if (NULL == data) { + return INV_ERROR_INVALID_PARAMETER; + } + + msg.address = MPUREG_FIFO_R_W; /* Not used */ + msg.length = length; + msg.data = data; + + result = ioctl((int)sl_handle, MPU_READ_FIFO, &msg); + if (result != INV_SUCCESS) { + MPL_LOGE("I2C Error %08x: could not read fifo: R:%02x L:%d\n", + result, MPUREG_FIFO_R_W, length); + return INV_ERROR_SERIAL_READ; + } else if (SERIAL_FULL_DEBUG) { + char data_buff[4096] = ""; + char strchar[3]; + int ii; + for (ii = 0; ii < length; ii++) { + snprintf(strchar, sizeof(strchar), "%02x", data[0]); + strncat(data_buff, strchar, sizeof(data_buff)); + } + MPL_LOGI("I2C ReadFifo Success %02x %02x: %s\n", + MPUREG_FIFO_R_W, length, data_buff); + } + return INV_SUCCESS; +} + +/** + * @} + */ + + |