Skip to contentSkip to conversation

iio: ak8975: Fix calculation formula for convert micro tesla to gauss unit

PATCH RESEND Applied Beomho Seo 2 participants 3 messages Feb 4, 2014 – Feb 8, 2014 IIO

lore
Share & tools
lore

Beomho Seo

author
#0 lore raw

PATCH RESEND 1/2 iio: ak8975: Fix calculation formula for convert micro tesla to gauss unit

One micro tesla equal 0.01 gauss. So I have fixed calculation formula And add RAW_TO_GAUSS macro. ASA is in the range of 0 to 255. If multiply 0.003, calculation result(in_magn_[*]_scale) is always 0. So multiply 3000 and return and IIO_VAL_INT_PLUS_MICRO.
As a result, read_raw call back function return accurate scale value.

---
 drivers/iio/magnetometer/ak8975.c |   16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)
drivers/iio/magnetometer/ak8975.c +9 -7
index ff284e5..0542354 100644
@@ -85,6 +85,7 @@
 #define AK8975_MAX_CONVERSION_TIMEOUT	500
 #define AK8975_CONVERSION_DONE_POLL_TIME 10
 #define AK8975_DATA_READY_TIMEOUT	((100*HZ)/1000)
+#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256)
 
 /*
  * Per-instance context data for the device.
@@ -265,15 +266,15 @@ static int ak8975_setup(struct i2c_client *client)
  *
  * Since 1uT = 0.01 gauss, our final scale factor becomes:
  *
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
+ * Hadj = H * ((ASA + 128) * 0.003) / 256
  *
  * Since ASA doesn't change, we cache the resultant scale factor into the
  * device context in ak8975_setup().
  */
-	data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
-	data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
-	data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
+	data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]);
+	data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]);
+	data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]);
 
 	return 0;
 }
@@ -428,8 +429,9 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
 	case IIO_CHAN_INFO_RAW:
 		return ak8975_read_axis(indio_dev, chan->address, val);
 	case IIO_CHAN_INFO_SCALE:
-		*val = data->raw_to_gauss[chan->address];
-		return IIO_VAL_INT;
+		*val = 0;
+		*val2 = data->raw_to_gauss[chan->address];
+		return IIO_VAL_INT_PLUS_MICRO;
 	}
 	return -EINVAL;
 }
Signature · 5 lines
1.7.9.5


-- 
Best Regards,
maintainer Applied
#1 lore raw
Quoted 7 lines · Beomho Seo

One micro tesla equal 0.01 gauss. So I have fixed calculation formula And add RAW_TO_GAUSS macro. ASA is in the range of 0 to 255. If multiply 0.003, calculation result(in_magn_[*]_scale) is always 0. So multiply 3000 and return and IIO_VAL_INT_PLUS_MICRO.
As a result, read_raw call back function return accurate scale value.

Applied to the fixes-togreg branch of iio.git

Thanks,

Quoted 50 lines
---
  drivers/iio/magnetometer/ak8975.c |   16 +++++++++-------
  1 file changed, 9 insertions(+), 7 deletions(-)
drivers/iio/magnetometer/ak8975.c +9 -7
index ff284e5..0542354 100644
@@ -85,6 +85,7 @@
  #define AK8975_MAX_CONVERSION_TIMEOUT	500
  #define AK8975_CONVERSION_DONE_POLL_TIME 10
  #define AK8975_DATA_READY_TIMEOUT	((100*HZ)/1000)
+#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256)
 
  /*
   * Per-instance context data for the device.
@@ -265,15 +266,15 @@ static int ak8975_setup(struct i2c_client *client)
   *
   * Since 1uT = 0.01 gauss, our final scale factor becomes:
   *
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
+ * Hadj = H * ((ASA + 128) * 0.003) / 256
   *
   * Since ASA doesn't change, we cache the resultant scale factor into the
   * device context in ak8975_setup().
   */
-	data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
-	data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
-	data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
+	data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]);
+	data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]);
+	data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]);
 
  	return 0;
  }
@@ -428,8 +429,9 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
  	case IIO_CHAN_INFO_RAW:
  		return ak8975_read_axis(indio_dev, chan->address, val);
  	case IIO_CHAN_INFO_SCALE:
-		*val = data->raw_to_gauss[chan->address];
-		return IIO_VAL_INT;
+		*val = 0;
+		*val2 = data->raw_to_gauss[chan->address];
+		return IIO_VAL_INT_PLUS_MICRO;
  	}
  	return -EINVAL;
  }
maintainer
#2 lore raw
Quoted 11 lines · Jonathan Cameron
Quoted 7 lines · Beomho Seo

One micro tesla equal 0.01 gauss. So I have fixed calculation formula And add RAW_TO_GAUSS macro. ASA is in the range of 0 to 255. If multiply 0.003, calculation result(in_magn_[*]_scale) is always 0. So multiply 3000 and return and IIO_VAL_INT_PLUS_MICRO.
As a result, read_raw call back function return accurate scale value.

Applied to the fixes-togreg branch of iio.git

Thanks,

I forgot to mention that I added a line to the description on what the effect of the bug was and also marked this for stable.

Thanks,

Jonathan

Quoted 55 lines
Quoted 40 lines
---
  drivers/iio/magnetometer/ak8975.c |   16 +++++++++-------
  1 file changed, 9 insertions(+), 7 deletions(-)
drivers/iio/magnetometer/ak8975.c +6 -5
index ff284e5..0542354 100644
@@ -85,6 +85,7 @@
  #define AK8975_MAX_CONVERSION_TIMEOUT    500
  #define AK8975_CONVERSION_DONE_POLL_TIME 10
  #define AK8975_DATA_READY_TIMEOUT    ((100*HZ)/1000)
+#define RAW_TO_GAUSS(asa) ((((asa) + 128) * 3000) / 256)
 
  /*
   * Per-instance context data for the device.
@@ -265,15 +266,15 @@ static int ak8975_setup(struct i2c_client *client)
   *
   * Since 1uT = 0.01 gauss, our final scale factor becomes:
   *
- * Hadj = H * ((ASA + 128) / 256) * 3/10 * 100
- * Hadj = H * ((ASA + 128) * 30 / 256
+ * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
+ * Hadj = H * ((ASA + 128) * 0.003) / 256
   *
   * Since ASA doesn't change, we cache the resultant scale factor into the
   * device context in ak8975_setup().
   */
-    data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
-    data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8;
-    data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
+    data->raw_to_gauss[0] = RAW_TO_GAUSS(data->asa[0]);
+    data->raw_to_gauss[1] = RAW_TO_GAUSS(data->asa[1]);
+    data->raw_to_gauss[2] = RAW_TO_GAUSS(data->asa[2]);
 
      return 0;
  }
@@ -428,8 +429,9 @@ static int ak8975_read_raw(struct iio_dev *indio_dev,
      case IIO_CHAN_INFO_RAW:

drivers/iio/magnetometer/ak8975.c static int ak8975_read_raw(struct iio_dev *indio_dev, · line 437

Quoted 10 lines
drivers/iio/magnetometer/ak8975.c +3 -2
          return ak8975_read_axis(indio_dev, chan->address, val);
      case IIO_CHAN_INFO_SCALE:
-        *val = data->raw_to_gauss[chan->address];
-        return IIO_VAL_INT;
+        *val = 0;
+        *val2 = data->raw_to_gauss[chan->address];
+        return IIO_VAL_INT_PLUS_MICRO;
      }
      return -EINVAL;
  }

--
To unsubscribe from this list: send the line "unsubscribe linux-iio" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html