فهرست منبع

v3.6.0
Added Fast offset compensation

Bosch Sensortec 8 سال پیش
والد
کامیت
b09262fb23
5فایلهای تغییر یافته به همراه687 افزوده شده و 19 حذف شده
  1. 131 5
      README.md
  2. 325 9
      bmi160.c
  3. 95 2
      bmi160.h
  4. 128 3
      bmi160_defs.h
  5. 8 0
      changelog.md

+ 131 - 5
README.md

@@ -5,11 +5,11 @@ This package contains the Bosch Sensortec's BMI160 sensor driver (sensor API)
 The sensor driver package includes bmi160.h, bmi160.c and bmi160_defs.h files
 
 ## Version
-File | Version | Date
------|---------|-----
-bmi160.c |   3.5.0    |   13 Apr 2017
-bmi160.h |   3.5.0   |    13 Apr 2017
-bmi160_defs.h |   3.5.0    |   13 Apr 2017
+File          | Version | Date
+--------------|---------|---------------
+bmi160.c      |   3.6.0 |   04 Aug 2017
+bmi160.h      |   3.6.0 |   04 Aug 2017
+bmi160_defs.h |   3.6.0 |   04 Aug 2017
 
 ## Integration details
 * Integrate bmi160.h, bmi160_defs.h and bmi160.c file in to your project.
@@ -518,4 +518,130 @@ int8_t fifo_gyro_header_time_data(struct bmi160_dev *dev)
 }
 ```
 
+## FOC and offset compensation
+> FOC shouldnot be used in Low-power mode
+#### Example for configuring FOC for accel and gyro
+```
+/* An example for configuring FOC for accel and gyro data */
+int8_t start_foc(struct bmi160_dev *dev)
+{
+	int8_t rslt = 0;
+	/* FOC configuration structure */
+	struct bmi160_foc_conf foc_conf;
+	/* Structure to store the offsets */
+	struct bmi160_offsets offsets;
+	
+	/* Enable FOC for accel with target values of z = 1g ; x,y as 0g */
+	foc_conf.acc_off_en = BMI160_ENABLE;
+	foc_conf.foc_acc_x  = BMI160_FOC_ACCEL_0G;
+	foc_conf.foc_acc_y  = BMI160_FOC_ACCEL_0G;
+	foc_conf.foc_acc_z  = BMI160_FOC_ACCEL_POSITIVE_G;
+	
+	/* Enable FOC for gyro */
+	foc_conf.foc_gyr_en = BMI160_ENABLE;
+	foc_conf.gyro_off_en = BMI160_ENABLE;
+
+	rslt = bmi160_start_foc(&foc_conf, &offsets, sen);
+	
+	if (rslt == BMI160_OK) {
+		printf("\n FOC DONE SUCCESSFULLY ");
+		printf("\n OFFSET VALUES AFTER FOC : ");
+		printf("\n OFFSET VALUES ACCEL X : %d ",offsets.off_acc_x);
+		printf("\n OFFSET VALUES ACCEL Y : %d ",offsets.off_acc_y);
+		printf("\n OFFSET VALUES ACCEL Z : %d ",offsets.off_acc_z);
+		printf("\n OFFSET VALUES GYRO  X : %d ",offsets.off_gyro_x);
+		printf("\n OFFSET VALUES GYRO  Y : %d ",offsets.off_gyro_y);
+		printf("\n OFFSET VALUES GYRO  Z : %d ",offsets.off_gyro_z);	
+	}
+	
+	/* After start of FOC offsets will be updated automatically and 
+	 * the data will be very much close to the target values of measurement */
+
+	return rslt;
+}
+```
+
+#### Example for updating the offsets manually
+> The offsets set by this method will be reset on soft-reset/POR 
+```
+/* An example for updating manual offsets to sensor */
+int8_t write_offsets(struct bmi160_dev *dev)
+{
+	int8_t rslt = 0;
+	/* FOC configuration structure */
+	struct bmi160_foc_conf foc_conf;
+	/* Structure to store the offsets */
+	struct bmi160_offsets offsets;
+	
+	/* Enable offset update for accel */
+	foc_conf.acc_off_en = BMI160_ENABLE;
+
+	/* Enable offset update for gyro */
+	foc_conf.gyro_off_en = BMI160_ENABLE;
+	
+	/* offset values set by user */
+	offsets.off_acc_x = 0x10;
+	offsets.off_acc_y = 0x10;
+	offsets.off_acc_z = 0x10;
+	offsets.off_gyro_x = 0x10;
+	offsets.off_gyro_y = 0x10;
+	offsets.off_gyro_z = 0x10;
+
+	rslt = bmi160_set_offsets(&foc_conf, &offsets, sen);
+	
+	/* After offset setting the data read from the 
+	 * sensor will have the corresponding offset */
+	
+	return rslt;
+}
+```
+
+#### Example for updating the offsets into NVM
+> The offsets set by this method will be present in NVM and will be 
+> restored on POR/soft-reset
+```
+/* An example for updating manual offsets to sensor */
+int8_t write_offsets_nvm(struct bmi160_dev *dev)
+{
+	int8_t rslt = 0;
+	/* FOC configuration structure */
+	struct bmi160_foc_conf foc_conf;
+	/* Structure to store the offsets */
+	struct bmi160_offsets offsets;
+	
+	/* Enable offset update for accel */
+	foc_conf.acc_off_en = BMI160_ENABLE;
+
+	/* Enable offset update for gyro */
+	foc_conf.gyro_off_en = BMI160_ENABLE;
+	
+	/* offset values set by user as per their reference 
+	 * Resolution of accel = 3.9mg/LSB 
+	 * Resolution of gyro  = (0.061degrees/second)/LSB */
+	offsets.off_acc_x = 10;
+	offsets.off_acc_y = -15;
+	offsets.off_acc_z = 20;
+	offsets.off_gyro_x = 30;
+	offsets.off_gyro_y = -35;
+	offsets.off_gyro_z = -40;
+
+	rslt = bmi160_set_offsets(&foc_conf, &offsets, sen);
+	 
+	if (rslt == BMI160_OK) {
+		/* Update the NVM */
+		rslt = bmi160_update_nvm(dev);
+	}
+	
+	/* After this procedure the offsets are written to 
+	 * NVM and restored on POR/soft-reset 
+	 * The set values can be removed to ideal case by 
+	 * invoking the following APIs
+	 *     - bmi160_start_foc()	 
+	 *     - bmi160_update_nvm()
+	 */
+
+	return rslt;
+}
+```
+
 ## Copyright (C) 2016 - 2017 Bosch Sensortec GmbH

+ 325 - 9
bmi160.c

@@ -40,8 +40,8 @@
  * patent rights of the copyright holder.
  *
  * @file    bmi160.c
- * @date    13 Apr 2017
- * @version 3.5.0
+ * @date    04 Aug 2017
+ * @version 3.6.0
  * @brief
  *
  */
@@ -1298,8 +1298,8 @@ static void move_next_frame(uint16_t *data_index, uint8_t current_frame_length,
  *  FIFO data in the structure instance dev.
  *
  *  @param[in,out] data_index : Index of the FIFO data which
- *                             has the sensor time.
- *  @param[in] dev        : Structure instance of bma4_dev.
+ *                              has the sensor time.
+ *  @param[in] dev            : Structure instance of bmi160_dev.
  *
  *  @return Result of API execution status
  *  @retval zero -> Success  / -ve value -> Error
@@ -1310,15 +1310,50 @@ static void unpack_sensortime_frame(uint16_t *data_index, const struct bmi160_de
  *  @brief This API is used to parse and store the skipped_frame_count from
  *  the FIFO data in the structure instance dev.
  *
- *  @param[in,out] data_index       : Index of the FIFO data which
+ *  @param[in,out] data_index   : Index of the FIFO data which
  *                                    has the skipped frame count.
- *  @param[in] dev              : Structure instance of bma4_dev.
+ *  @param[in] dev              : Structure instance of bmi160_dev.
  *
  *  @return Result of API execution status
  *  @retval zero -> Success  / -ve value -> Error
  */
 static void unpack_skipped_frame(uint16_t *data_index, const struct bmi160_dev *dev);
 
+/*!
+ *  @brief This API is used to get the FOC status from the sensor
+ *
+ *  @param[in,out] foc_status   : Result of FOC status.
+ *  @param[in] dev              : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t get_foc_status(uint8_t *foc_status, struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API is used to configure the offset enable bits in the sensor
+ *
+ *  @param[in,out] foc_conf   : Structure instance of bmi160_foc_conf which
+ *                                   has the FOC and offset configurations
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t configure_offset_enable(const struct bmi160_foc_conf *foc_conf, struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API is used to trigger the FOC in the sensor
+ *
+ *  @param[in,out] offset     : Structure instance of bmi160_offsets which
+ *                              reads and stores the offset values after FOC
+ *  @param[in] dev            : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval zero -> Success  / -ve value -> Error
+ */
+static int8_t trigger_foc(struct bmi160_offsets *offset, struct bmi160_dev const *dev);
+
 /*********************** User function definitions ****************************/
 
 /*!
@@ -1911,7 +1946,7 @@ int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev)
 	uint8_t addr = BMI160_FIFO_DATA_ADDR;
 
 	/* check the bmi160 structure as NULL*/
-	if (dev == NULL || dev->fifo->data == NULL) {
+	if ((dev == NULL) || (dev->fifo->data == NULL)) {
 		rslt = BMI160_E_NULL_PTR;
 	} else {
 		reset_fifo_data_structure(dev);
@@ -1925,7 +1960,8 @@ int8_t bmi160_get_fifo_data(struct bmi160_dev const *dev)
 				dev->fifo->length = bytes_to_read;
 			}
 
-			if ((dev->fifo->fifo_time_enable == BMI160_FIFO_TIME_ENABLE) &&  (bytes_to_read + 4 <= user_fifo_len)) {
+			if ((dev->fifo->fifo_time_enable == BMI160_FIFO_TIME_ENABLE)
+				&& (bytes_to_read + 4 <= user_fifo_len)) {
 				/* Handling case of sensor time availability */
 				dev->fifo->length = dev->fifo->length + 4;
 			}
@@ -2130,6 +2166,193 @@ int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_l
 	return rslt;
 }
 
+/*!
+ *  @brief This API starts the FOC of accel and gyro
+ *
+ *  @note FOC should not be used in low-power mode of sensor
+ *
+ *  @note Accel FOC targets values of +1g , 0g , -1g
+ *  Gyro FOC always targets value of 0 dps
+ */
+int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf, struct bmi160_offsets *offset,
+				struct bmi160_dev const *dev)
+{
+	int8_t rslt;
+	uint8_t data;
+
+	/* Null-pointer check */
+	rslt = null_ptr_check(dev);
+
+	if (rslt != BMI160_OK) {
+		rslt = BMI160_E_NULL_PTR;
+	} else {
+		/* Set the offset enable bits */
+		rslt = configure_offset_enable(foc_conf, dev);
+		if (rslt == BMI160_OK) {
+			/* Read the FOC config from the sensor */
+			rslt = bmi160_get_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev);
+
+			/* Set the FOC config for gyro */
+			data = BMI160_SET_BITS(data, BMI160_GYRO_FOC_EN, foc_conf->foc_gyr_en);
+
+			/* Set the FOC config for accel xyz axes */
+			data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_X_CONF, foc_conf->foc_acc_x);
+			data = BMI160_SET_BITS(data, BMI160_ACCEL_FOC_Y_CONF, foc_conf->foc_acc_y);
+			data = BMI160_SET_BITS_POS_0(data, BMI160_ACCEL_FOC_Z_CONF, foc_conf->foc_acc_z);
+
+			if (rslt == BMI160_OK) {
+				/* Set the FOC config in the sensor */
+				rslt = bmi160_set_regs(BMI160_FOC_CONF_ADDR, &data, 1, dev);
+				if (rslt == BMI160_OK) {
+					/* Procedure to trigger
+					 * FOC and check status */
+					rslt = trigger_foc(offset, dev);
+				}
+			}
+		}
+	}
+
+	return rslt;
+}
+
+/*!
+ *  @brief This API reads and stores the offset values of accel and gyro
+ */
+int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev)
+{
+	int8_t rslt;
+	uint8_t data[7];
+	uint8_t lsb, msb;
+	int16_t offset_msb, offset_lsb;
+	int16_t offset_data;
+
+
+	/* Null-pointer check */
+	rslt = null_ptr_check(dev);
+
+	if (rslt != BMI160_OK) {
+		rslt = BMI160_E_NULL_PTR;
+	} else {
+		/* Read the FOC config from the sensor */
+		rslt = bmi160_get_regs(BMI160_OFFSET_ADDR, data, 7, dev);
+
+		/* Accel offsets */
+		offset->off_acc_x = (int8_t)data[0];
+		offset->off_acc_y = (int8_t)data[1];
+		offset->off_acc_z = (int8_t)data[2];
+
+		/* Gyro x-axis offset */
+		lsb = data[3];
+		msb = BMI160_GET_BITS_POS_0(data[6], BMI160_GYRO_OFFSET_X);
+		offset_msb = (int16_t)(msb << 14);
+		offset_lsb = lsb << 6;
+		offset_data = offset_msb | offset_lsb;
+		/* Divide by 64 to get the Right shift by 6 value */
+		offset->off_gyro_x = (int16_t)(offset_data / 64);
+
+		/* Gyro y-axis offset */
+		lsb = data[4];
+		msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Y);
+		offset_msb = (int16_t)(msb << 14);
+		offset_lsb = lsb << 6;
+		offset_data = offset_msb | offset_lsb;
+		/* Divide by 64 to get the Right shift by 6 value */
+		offset->off_gyro_y = (int16_t)(offset_data / 64);
+
+		/* Gyro z-axis offset */
+		lsb = data[5];
+		msb = BMI160_GET_BITS(data[6], BMI160_GYRO_OFFSET_Z);
+		offset_msb = (int16_t)(msb << 14);
+		offset_lsb = lsb << 6;
+		offset_data = offset_msb | offset_lsb;
+		/* Divide by 64 to get the Right shift by 6 value */
+		offset->off_gyro_z = (int16_t)(offset_data / 64);
+	}
+
+	return rslt;
+}
+
+/*!
+ *  @brief This API writes the offset values of accel and gyro to
+ *  the sensor but these values will be reset on POR or soft reset.
+ */
+int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf, const struct bmi160_offsets *offset,
+				struct bmi160_dev const *dev)
+{
+	int8_t rslt;
+	uint8_t data[7];
+	uint8_t x_msb, y_msb, z_msb;
+
+
+	/* Null-pointer check */
+	rslt = null_ptr_check(dev);
+
+	if (rslt != BMI160_OK) {
+		rslt = BMI160_E_NULL_PTR;
+	} else {
+		/* Update the accel offset */
+		data[0] = (uint8_t)offset->off_acc_x;
+		data[1] = (uint8_t)offset->off_acc_y;
+		data[2] = (uint8_t)offset->off_acc_z;
+
+		/* Update the LSB of gyro offset */
+		data[3] = BMI160_GET_LSB(offset->off_gyro_x);
+		data[4] = BMI160_GET_LSB(offset->off_gyro_y);
+		data[5] = BMI160_GET_LSB(offset->off_gyro_z);
+
+		/* Update the MSB of gyro offset */
+		x_msb = BMI160_GET_BITS(offset->off_gyro_x, BMI160_GYRO_OFFSET);
+		y_msb = BMI160_GET_BITS(offset->off_gyro_y, BMI160_GYRO_OFFSET);
+		z_msb = BMI160_GET_BITS(offset->off_gyro_z, BMI160_GYRO_OFFSET);
+		data[6] = (uint8_t)(z_msb << 4 | y_msb << 2 | x_msb);
+
+		/* Set the offset enable/disable for gyro and accel */
+		data[6] = BMI160_SET_BITS(data[6], BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en);
+		data[6] = BMI160_SET_BITS(data[6], BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en);
+
+		/* Set the offset config and values in the sensor */
+		rslt = bmi160_set_regs(BMI160_OFFSET_ADDR, data, 7, dev);
+	}
+
+	return rslt;
+}
+
+/*!
+ *  @brief This API writes the image registers values to NVM which is
+ *  stored even after POR or soft reset
+ */
+int8_t bmi160_update_nvm(struct bmi160_dev const *dev)
+{
+	int8_t rslt;
+	uint8_t data;
+	uint8_t cmd = BMI160_NVM_BACKUP_EN;
+
+	/* Read the nvm_prog_en configuration */
+	rslt = bmi160_get_regs(BMI160_CONF_ADDR, &data, 1, dev);
+	if (rslt == BMI160_OK) {
+		data = BMI160_SET_BITS(data, BMI160_NVM_UPDATE, 1);
+		/* Set the nvm_prog_en bit in the sensor */
+		rslt = bmi160_set_regs(BMI160_CONF_ADDR, &data, 1, dev);
+		if (rslt == BMI160_OK) {
+			/* Update NVM */
+			rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev);
+			if (rslt == BMI160_OK) {
+				/* Check for NVM ready status */
+				rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev);
+				if (rslt == BMI160_OK) {
+					data = BMI160_GET_BITS(data, BMI160_NVM_STATUS);
+					if (data != BMI160_ENABLE) {
+						/* Delay to update NVM */
+						dev->delay_ms(25);
+					}
+				}
+			}
+		}
+	}
+
+	return rslt;
+}
+
 /*********************** Local function definitions ***************************/
 
 /*!
@@ -2776,7 +2999,7 @@ static int8_t set_accel_pwr(struct bmi160_dev *dev)
 		if (dev->accel_cfg.power != dev->prev_accel_cfg.power) {
 			rslt = process_under_sampling(&data, dev);
 			if (rslt == BMI160_OK) {
-					/* Write accel power */
+				/* Write accel power */
 				rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &dev->accel_cfg.power, 1, dev);
 				/* Add delay of 5 ms */
 				if (dev->prev_accel_cfg.power == BMI160_ACCEL_SUSPEND_MODE)
@@ -5272,4 +5495,97 @@ static void unpack_skipped_frame(uint16_t *data_index, const struct bmi160_dev *
 	}
 }
 
+/*!
+ *  @brief This API is used to get the FOC status from the sensor
+ */
+static int8_t get_foc_status(uint8_t *foc_status, struct bmi160_dev const *dev)
+{
+	int8_t rslt;
+	uint8_t data;
+
+	/* Read the FOC status from sensor */
+	rslt = bmi160_get_regs(BMI160_STATUS_ADDR, &data, 1, dev);
+	if (rslt == BMI160_OK) {
+		/* Get the foc_status bit */
+		*foc_status = BMI160_GET_BITS(data, BMI160_FOC_STATUS);
+	}
+
+	return rslt;
+}
+
+/*!
+ *  @brief This API is used to configure the offset enable bits in the sensor
+ */
+static int8_t configure_offset_enable(const struct bmi160_foc_conf *foc_conf, struct bmi160_dev const *dev)
+{
+	int8_t rslt;
+	uint8_t data;
+
+	/* Null-pointer check */
+	rslt = null_ptr_check(dev);
+
+	if (rslt != BMI160_OK) {
+		rslt = BMI160_E_NULL_PTR;
+	} else {
+		/* Read the FOC config from the sensor */
+		rslt = bmi160_get_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev);
+
+		if (rslt == BMI160_OK) {
+			/* Set the offset enable/disable for gyro */
+			data = BMI160_SET_BITS(data, BMI160_GYRO_OFFSET_EN, foc_conf->gyro_off_en);
+
+			/* Set the offset enable/disable for accel */
+			data = BMI160_SET_BITS(data, BMI160_ACCEL_OFFSET_EN, foc_conf->acc_off_en);
+
+			/* Set the offset config in the sensor */
+			rslt = bmi160_set_regs(BMI160_OFFSET_CONF_ADDR, &data, 1, dev);
+		}
+	}
+
+	return rslt;
+}
+
+static int8_t trigger_foc(struct bmi160_offsets *offset, struct bmi160_dev const *dev)
+{
+	int8_t rslt;
+	uint8_t foc_status;
+	uint8_t cmd = BMI160_START_FOC_CMD;
+	uint8_t timeout = 0;
+	uint8_t data_array[20];
+
+	/* Start the FOC process */
+	rslt = bmi160_set_regs(BMI160_COMMAND_REG_ADDR, &cmd, 1, dev);
+	if (rslt == BMI160_OK) {
+		/* Check the FOC status*/
+		rslt = get_foc_status(&foc_status, dev);
+		if ((rslt != BMI160_OK) || (foc_status != BMI160_ENABLE)) {
+			while ((foc_status != BMI160_ENABLE) && (timeout < 11)) {
+				/* Maximum time of 250ms is given in 10
+				 * steps of 25ms each */
+				dev->delay_ms(25);
+				/* Check the FOC status*/
+				rslt = get_foc_status(&foc_status, dev);
+				timeout++;
+			}
+
+			if ((rslt == BMI160_OK) && (foc_status == BMI160_ENABLE)) {
+				/* Get offset values from sensor */
+				rslt = bmi160_get_offsets(offset, dev);
+			} else {
+				/* FOC failure case */
+				rslt = BMI160_FOC_FAILURE;
+			}
+		}
+
+		if (rslt == BMI160_OK) {
+			/* Read registers 0x04-0x17 */
+			rslt = bmi160_get_regs(BMI160_GYRO_DATA_ADDR,
+				data_array, 20, dev);
+		}
+	}
+
+
+	return rslt;
+}
+
 /** @}*/

+ 95 - 2
bmi160.h

@@ -40,8 +40,8 @@
  * patent rights of the copyright holder.
  *
  * @file    bmi160.h
- * @date    13 Apr 2017
- * @version 3.5.0
+ * @date    04 Aug 2017
+ * @version 3.6.0
  * @brief
  *
  */
@@ -516,6 +516,99 @@ int8_t bmi160_extract_accel(struct bmi160_sensor_data *accel_data, uint8_t *acce
  */
 int8_t bmi160_extract_gyro(struct bmi160_sensor_data *gyro_data, uint8_t *gyro_length, struct bmi160_dev const *dev);
 
+/*!
+ *  @brief This API starts the FOC of accel and gyro
+ *
+ *  @note FOC should not be used in low-power mode of sensor
+ *
+ *  @note Accel FOC targets values of +1g , 0g , -1g
+ *  Gyro FOC always targets value of 0 dps
+ *
+ *  @param[in] foc_conf    : Structure instance of bmi160_foc_conf which
+ *                                   has the FOC configuration
+ *  @param[in,out] offset  : Structure instance to store Offset
+ *                                   values read from sensor
+ *  @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *  @note Pre-requisites for triggering FOC in accel , Set the following,
+ *   Enable the acc_off_en
+ *       Ex :  foc_conf.acc_off_en = BMI160_ENABLE;
+ *
+ *   Set the desired target values of FOC to each axes (x,y,z) by using the
+ *   following macros
+ *       - BMI160_FOC_ACCEL_DISABLED
+ *       - BMI160_FOC_ACCEL_POSITIVE_G
+ *       - BMI160_FOC_ACCEL_NEGATIVE_G
+ *       - BMI160_FOC_ACCEL_0G
+ *
+ *   Ex : foc_conf.foc_acc_x  = BMI160_FOC_ACCEL_0G;
+ *        foc_conf.foc_acc_y  = BMI160_FOC_ACCEL_0G;
+ *        foc_conf.foc_acc_z  = BMI160_FOC_ACCEL_POSITIVE_G;
+ *
+ *  @note Pre-requisites for triggering FOC in gyro ,
+ *  Set the following parameters,
+ *
+ *   Ex : foc_conf.foc_gyr_en = BMI160_ENABLE;
+ *        foc_conf.gyro_off_en = BMI160_ENABLE;
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_start_foc(const struct bmi160_foc_conf *foc_conf, struct bmi160_offsets *offset,
+				struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API reads and stores the offset values of accel and gyro
+ *
+ *  @param[in,out] offset : Structure instance of bmi160_offsets in which
+ *                          the offset values are read and stored
+ *  @param[in] dev        : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_get_offsets(struct bmi160_offsets *offset, const struct bmi160_dev *dev);
+
+/*!
+ *  @brief This API writes the offset values of accel and gyro to
+ *  the sensor but these values will be reset on POR or soft reset.
+ *
+ *  @param[in] foc_conf    : Structure instance of bmi160_foc_conf which
+ *                                   has the FOC configuration
+ *  @param[in] offset      : Structure instance in which user updates offset
+ *                            values which are to be written in the sensor
+ *  @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *  @note Offsets can be set by user like offset->off_acc_x = 10;
+ *  where 1LSB = 3.9mg and for gyro 1LSB = 0.061degrees/second
+ *
+ * @note BMI160 offset values for xyz axes of accel should be within range of
+ *  BMI160_ACCEL_MIN_OFFSET (-128) to BMI160_ACCEL_MAX_OFFSET (127)
+ *
+ * @note BMI160 offset values for xyz axes of gyro should be within range of
+ *  BMI160_GYRO_MIN_OFFSET (-512) to BMI160_GYRO_MAX_OFFSET (511)
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_set_offsets(const struct bmi160_foc_conf *foc_conf, const struct bmi160_offsets *offset,
+				struct bmi160_dev const *dev);
+
+/*!
+ *  @brief This API writes the image registers values to NVM which is
+ *  stored even after POR or soft reset
+ *
+ *  @param[in] dev         : Structure instance of bmi160_dev.
+ *
+ *  @return Result of API execution status
+ *  @retval 0 -> Success
+ *  @retval Any non zero value -> Fail
+ */
+int8_t bmi160_update_nvm(struct bmi160_dev const *dev);
+
 #ifdef __cplusplus
 }
 #endif

+ 128 - 3
bmi160_defs.h

@@ -40,8 +40,8 @@
  * patent rights of the copyright holder.
  *
  * @file    bmi160_defs.h
- * @date    13 Apr 2017
- * @version 3.5.0
+ * @date    04 Aug 2017
+ * @version 3.6.0
  * @brief
  *
  */
@@ -57,6 +57,7 @@
 /*************************** C types headers *****************************/
 #ifdef __KERNEL__
 #include <linux/types.h>
+#include <linux/kernel.h>
 #else
 #include <stdint.h>
 #include <stddef.h>
@@ -69,11 +70,13 @@ extern "C"
 #endif
 
 /*************************** Common macros   *****************************/
+#ifdef __KERNEL__
 #if (LONG_MAX) > 0x7fffffff
 #define __have_long64 1
 #elif (LONG_MAX) == 0x7fffffff
 #define __have_long32 1
 #endif
+#endif
 
 #if !defined(UINT8_C)
 #define INT8_C(x)       x
@@ -302,7 +305,6 @@ extern "C"
 #define BMI160_AUX_IF_2_ADDR		UINT8_C(0x4D)
 #define BMI160_AUX_IF_3_ADDR		UINT8_C(0x4E)
 #define BMI160_AUX_IF_4_ADDR		UINT8_C(0x4F)
-
 #define BMI160_INT_ENABLE_0_ADDR         UINT8_C(0x50)
 #define BMI160_INT_ENABLE_1_ADDR         UINT8_C(0x51)
 #define BMI160_INT_ENABLE_2_ADDR         UINT8_C(0x52)
@@ -328,8 +330,13 @@ extern "C"
 #define BMI160_INT_ORIENT_1_ADDR         UINT8_C(0x66)
 #define BMI160_INT_FLAT_0_ADDR           UINT8_C(0x67)
 #define BMI160_INT_FLAT_1_ADDR           UINT8_C(0x68)
+#define BMI160_FOC_CONF_ADDR             UINT8_C(0x69)
+#define BMI160_CONF_ADDR                 UINT8_C(0x6A)
+
 #define BMI160_IF_CONF_ADDR		 UINT8_C(0x6B)
 #define BMI160_SELF_TEST_ADDR		 UINT8_C(0x6D)
+#define BMI160_OFFSET_ADDR		 UINT8_C(0x71)
+#define BMI160_OFFSET_CONF_ADDR		 UINT8_C(0x77)
 #define BMI160_INT_STEP_CNT_0_ADDR	 UINT8_C(0x78)
 #define BMI160_INT_STEP_CONFIG_0_ADDR    UINT8_C(0x7A)
 #define BMI160_INT_STEP_CONFIG_1_ADDR    UINT8_C(0x7B)
@@ -349,6 +356,7 @@ extern "C"
 #define BMI160_E_LWP_PRE_FLTR_INT_INVALID INT8_C(-8)
 #define BMI160_E_LWP_PRE_FLTR_INVALID	  INT8_C(-9)
 #define BMI160_E_AUX_NOT_FOUND		  INT8_C(-10)
+#define BMI160_FOC_FAILURE		  INT8_C(-11)
 
 /**\name API warning codes */
 #define BMI160_W_GYRO_SELF_TEST_FAIL	INT8_C(1)
@@ -360,6 +368,10 @@ extern "C"
 /** Soft reset command */
 #define BMI160_SOFT_RESET_CMD            UINT8_C(0xb6)
 #define BMI160_SOFT_RESET_DELAY_MS       UINT8_C(15)
+/** Start FOC command */
+#define BMI160_START_FOC_CMD            UINT8_C(0x03)
+/** NVM backup enabling command */
+#define BMI160_NVM_BACKUP_EN		UINT8_C(0xA0)
 
 /* Delay in ms settings */
 #define BMI160_ACCEL_DELAY_MS            UINT8_C(5)
@@ -547,6 +559,12 @@ extern "C"
 #define FIFO_CONFIG_MSB_CHECK            UINT8_C(0x80)
 #define FIFO_CONFIG_LSB_CHECK            UINT8_C(0x00)
 
+/*! BMI160 accel FOC configurations */
+#define BMI160_FOC_ACCEL_DISABLED        UINT8_C(0x00)
+#define BMI160_FOC_ACCEL_POSITIVE_G      UINT8_C(0x01)
+#define BMI160_FOC_ACCEL_NEGATIVE_G      UINT8_C(0x02)
+#define BMI160_FOC_ACCEL_0G              UINT8_C(0x03)
+
 /** Array Parameter DefinItions */
 #define BMI160_SENSOR_TIME_LSB_BYTE      UINT8_C(0)
 #define BMI160_SENSOR_TIME_XLSB_BYTE     UINT8_C(1)
@@ -589,6 +607,14 @@ extern "C"
 /** BMI160 fifo flush Command */
 #define BMI160_FIFO_FLUSH_VALUE          UINT8_C(0xB0)
 
+/** BMI160 offset values for xyz axes of accel */
+#define BMI160_ACCEL_MIN_OFFSET         INT8_C(-128)
+#define BMI160_ACCEL_MAX_OFFSET         INT8_C(127)
+
+/** BMI160 offset values for xyz axes of gyro */
+#define BMI160_GYRO_MIN_OFFSET         INT16_C(-512)
+#define BMI160_GYRO_MAX_OFFSET         INT16_C(511)
+
 /** BMI160 fifo full interrupt position and mask */
 #define	BMI160_FIFO_FULL_INT_POS	UINT8_C(5)
 #define	BMI160_FIFO_FULL_INT_MSK	UINT8_C(0x20)
@@ -615,6 +641,43 @@ extern "C"
 #define BMI160_GYRO_SELF_TEST_STATUS_POS	UINT8_C(1)
 #define BMI160_GYRO_SELF_TEST_STATUS_MSK	UINT8_C(0x02)
 
+#define BMI160_GYRO_FOC_EN_POS	UINT8_C(6)
+#define BMI160_GYRO_FOC_EN_MSK	UINT8_C(0x40)
+
+#define BMI160_ACCEL_FOC_X_CONF_POS	UINT8_C(4)
+#define BMI160_ACCEL_FOC_X_CONF_MSK	UINT8_C(0x30)
+
+#define BMI160_ACCEL_FOC_Y_CONF_POS	UINT8_C(2)
+#define BMI160_ACCEL_FOC_Y_CONF_MSK	UINT8_C(0x0C)
+
+#define BMI160_ACCEL_FOC_Z_CONF_MSK	UINT8_C(0x03)
+
+#define BMI160_FOC_STATUS_POS	UINT8_C(3)
+#define BMI160_FOC_STATUS_MSK	UINT8_C(0x08)
+
+#define BMI160_GYRO_OFFSET_X_MSK	UINT8_C(0x03)
+
+#define BMI160_GYRO_OFFSET_Y_POS	UINT8_C(2)
+#define BMI160_GYRO_OFFSET_Y_MSK	UINT8_C(0x0C)
+
+#define BMI160_GYRO_OFFSET_Z_POS	UINT8_C(4)
+#define BMI160_GYRO_OFFSET_Z_MSK	UINT8_C(0x30)
+
+#define BMI160_GYRO_OFFSET_EN_POS	UINT8_C(7)
+#define BMI160_GYRO_OFFSET_EN_MSK	UINT8_C(0x80)
+
+#define BMI160_ACCEL_OFFSET_EN_POS	UINT8_C(6)
+#define BMI160_ACCEL_OFFSET_EN_MSK	UINT8_C(0x40)
+
+
+#define BMI160_GYRO_OFFSET_POS	        UINT16_C(8)
+#define BMI160_GYRO_OFFSET_MSK	        UINT16_C(0x0300)
+
+#define BMI160_NVM_UPDATE_POS	        UINT8_C(1)
+#define BMI160_NVM_UPDATE_MSK	        UINT8_C(0x02)
+
+#define BMI160_NVM_STATUS_POS	        UINT8_C(4)
+#define BMI160_NVM_STATUS_MSK	        UINT8_C(0x10)
 
 /* BIT SLICE GET AND SET FUNCTIONS */
 #define	BMI160_GET_BITS(regvar, bitname)\
@@ -629,6 +692,13 @@ extern "C"
 
 #define BMI160_GET_BITS_POS_0(reg_data, bitname)  (reg_data & (bitname##_MSK))
 
+/**\name UTILITY MACROS	*/
+#define BMI160_SET_LOW_BYTE     UINT16_C(0x00FF)
+#define BMI160_SET_HIGH_BYTE    UINT16_C(0xFF00)
+
+#define BMI160_GET_LSB(var)	(uint8_t)(var & BMI160_SET_LOW_BYTE)
+#define BMI160_GET_MSB(var)	(uint8_t)((var & BMI160_SET_HIGH_BYTE) >> 8)
+
 /*****************************************************************************/
 /* type definitions */
 typedef int8_t (*bmi160_com_fptr_t)(uint8_t dev_addr, uint8_t reg_addr,
@@ -652,6 +722,61 @@ struct bmi160_sensor_data {
 	uint32_t sensortime;
 };
 
+/*!
+ * @brief bmi160 FOC configuration structure
+ */
+struct bmi160_foc_conf {
+	/*! Enabling FOC in gyro
+	 * Assignable macros :
+	 *  - BMI160_ENABLE
+	 *  - BMI160_DISABLE
+	 */
+	uint8_t foc_gyr_en;
+
+	/*! Accel FOC configurations
+	 * Assignable macros :
+	 *  - BMI160_FOC_ACCEL_DISABLED
+	 *  - BMI160_FOC_ACCEL_POSITIVE_G
+	 *  - BMI160_FOC_ACCEL_NEGATIVE_G
+	 *  - BMI160_FOC_ACCEL_0G
+	 */
+	uint8_t foc_acc_x;
+	uint8_t foc_acc_y;
+	uint8_t foc_acc_z;
+
+	/*! Enabling offset compensation for accel in data registers
+	 * Assignable macros :
+	 *  - BMI160_ENABLE
+	 *  - BMI160_DISABLE
+	 */
+	uint8_t acc_off_en;
+
+	/*! Enabling offset compensation for gyro in data registers
+	 * Assignable macros :
+	 *  - BMI160_ENABLE
+	 *  - BMI160_DISABLE
+	 */
+	uint8_t gyro_off_en;
+};
+
+/*!
+ * @brief bmi160 accel gyro offsets
+ */
+struct bmi160_offsets {
+	/*! Accel offset for x axis */
+	int8_t off_acc_x;
+	/*! Accel offset for y axis */
+	int8_t off_acc_y;
+	/*! Accel offset for z axis */
+	int8_t off_acc_z;
+	/*! Gyro offset for x axis */
+	int16_t off_gyro_x;
+	/*! Gyro offset for y axis */
+	int16_t off_gyro_y;
+	/*! Gyro offset for z axis */
+	int16_t off_gyro_z;
+};
+
 /*!
  * @brief FIFO aux. sensor data structure
  */

+ 8 - 0
changelog.md

@@ -1,6 +1,14 @@
 # Change Log
 All notable changes to bmi160 Sensor API will be documented in this file. 
 
+## v3.6.0, 04 Aug 2017
+
+#### Added
+* Added interfaces for the following features 
+     - FOC
+     - Manual Offset compensation
+     - Offset compenation value update to NVM
+
 ## v3.5.0, 13 Apr 2017
 
 #### Added