7272#define HDC3020_MAX_TEMP_HYST_MICRO 164748607
7373#define HDC3020_MAX_HUM_MICRO 99220264
7474
75+ /* Divide 65535 from the datasheet by 5 to avoid overflows */
76+ #define HDC3020_THRESH_FRACTION (65535 / 5)
77+
7578struct hdc3020_data {
7679 struct i2c_client * client ;
7780 struct gpio_desc * reset_gpio ;
@@ -376,15 +379,18 @@ static int hdc3020_thresh_get_temp(u16 thresh)
376379 int temp ;
377380
378381 /*
379- * Get the temperature threshold from 9 LSBs, shift them to get
380- * the truncated temperature threshold representation and
381- * calculate the threshold according to the formula in the
382- * datasheet. Result is degree celsius scaled by 65535.
382+ * Get the temperature threshold from 9 LSBs, shift them to get the
383+ * truncated temperature threshold representation and calculate the
384+ * threshold according to the explicit formula in the datasheet:
385+ * T(C) = -45 + (175 * temp) / 65535.
386+ * Additionally scale by HDC3020_THRESH_FRACTION to avoid precision loss
387+ * when calculating threshold and hysteresis values. Result is degree
388+ * celsius scaled by HDC3020_THRESH_FRACTION.
383389 */
384390 temp = FIELD_GET (HDC3020_THRESH_TEMP_MASK , thresh ) <<
385391 HDC3020_THRESH_TEMP_TRUNC_SHIFT ;
386392
387- return -2949075 + (175 * temp );
393+ return -2949075 / 5 + (175 / 5 * temp );
388394}
389395
390396static int hdc3020_thresh_get_hum (u16 thresh )
@@ -394,13 +400,16 @@ static int hdc3020_thresh_get_hum(u16 thresh)
394400 /*
395401 * Get the humidity threshold from 7 MSBs, shift them to get the
396402 * truncated humidity threshold representation and calculate the
397- * threshold according to the formula in the datasheet. Result is
398- * percent scaled by 65535.
403+ * threshold according to the explicit formula in the datasheet:
404+ * RH(%) = 100 * hum / 65535.
405+ * Additionally scale by HDC3020_THRESH_FRACTION to avoid precision loss
406+ * when calculating threshold and hysteresis values. Result is percent
407+ * scaled by HDC3020_THRESH_FRACTION.
399408 */
400409 hum = FIELD_GET (HDC3020_THRESH_HUM_MASK , thresh ) <<
401410 HDC3020_THRESH_HUM_TRUNC_SHIFT ;
402411
403- return hum * 100 ;
412+ return hum * 100 / 5 ;
404413}
405414
406415static u16 hdc3020_thresh_set_temp (int s_temp , u16 curr_thresh )
@@ -455,8 +464,8 @@ int hdc3020_thresh_clr(s64 s_thresh, s64 s_hyst, enum iio_event_direction dir)
455464 else
456465 s_clr = s_thresh + s_hyst ;
457466
458- /* Divide by 65535 to get units of micro */
459- return div_s64 (s_clr , 65535 );
467+ /* Divide by HDC3020_THRESH_FRACTION to get units of micro */
468+ return div_s64 (s_clr , HDC3020_THRESH_FRACTION );
460469}
461470
462471static int _hdc3020_write_thresh (struct hdc3020_data * data , u16 reg , u16 val )
@@ -507,7 +516,7 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
507516
508517 clr = ret ;
509518 /* Scale value to include decimal part into calculations */
510- s_val = (val < 0 ) ? (val * 1000000 - val2 ) : (val * 1000000 + val2 );
519+ s_val = (val < 0 ) ? (val * 1000 - val2 ) : (val * 1000 + val2 );
511520 switch (chan -> type ) {
512521 case IIO_TEMP :
513522 switch (info ) {
@@ -523,7 +532,8 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
523532 /* Calculate old hysteresis */
524533 s_thresh = (s64 )hdc3020_thresh_get_temp (thresh ) * 1000000 ;
525534 s_clr = (s64 )hdc3020_thresh_get_temp (clr ) * 1000000 ;
526- s_hyst = div_s64 (abs (s_thresh - s_clr ), 65535 );
535+ s_hyst = div_s64 (abs (s_thresh - s_clr ),
536+ HDC3020_THRESH_FRACTION );
527537 /* Set new threshold */
528538 thresh = reg_val ;
529539 /* Set old hysteresis */
@@ -532,16 +542,17 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
532542 case IIO_EV_INFO_HYSTERESIS :
533543 /*
534544 * Function hdc3020_thresh_get_temp returns temperature
535- * in degree celsius scaled by 65535. Scale by 1000000
536- * to be able to subtract scaled hysteresis value.
545+ * in degree celsius scaled by HDC3020_THRESH_FRACTION.
546+ * Scale by 1000000 to be able to subtract scaled
547+ * hysteresis value.
537548 */
538549 s_thresh = (s64 )hdc3020_thresh_get_temp (thresh ) * 1000000 ;
539550 /*
540551 * Units of s_val are in micro degree celsius, scale by
541- * 65535 to get same units as s_thresh.
552+ * HDC3020_THRESH_FRACTION to get same units as s_thresh.
542553 */
543554 s_val = min (abs (s_val ), HDC3020_MAX_TEMP_HYST_MICRO );
544- s_hyst = (s64 )s_val * 65535 ;
555+ s_hyst = (s64 )s_val * HDC3020_THRESH_FRACTION ;
545556 s_clr = hdc3020_thresh_clr (s_thresh , s_hyst , dir );
546557 s_clr = max (s_clr , HDC3020_MIN_TEMP_MICRO );
547558 s_clr = min (s_clr , HDC3020_MAX_TEMP_MICRO );
@@ -565,7 +576,8 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
565576 /* Calculate old hysteresis */
566577 s_thresh = (s64 )hdc3020_thresh_get_hum (thresh ) * 1000000 ;
567578 s_clr = (s64 )hdc3020_thresh_get_hum (clr ) * 1000000 ;
568- s_hyst = div_s64 (abs (s_thresh - s_clr ), 65535 );
579+ s_hyst = div_s64 (abs (s_thresh - s_clr ),
580+ HDC3020_THRESH_FRACTION );
569581 /* Set new threshold */
570582 thresh = reg_val ;
571583 /* Try to set old hysteresis */
@@ -574,15 +586,16 @@ static int hdc3020_write_thresh(struct iio_dev *indio_dev,
574586 case IIO_EV_INFO_HYSTERESIS :
575587 /*
576588 * Function hdc3020_thresh_get_hum returns relative
577- * humidity in percent scaled by 65535. Scale by 1000000
578- * to be able to subtract scaled hysteresis value.
589+ * humidity in percent scaled by HDC3020_THRESH_FRACTION.
590+ * Scale by 1000000 to be able to subtract scaled
591+ * hysteresis value.
579592 */
580593 s_thresh = (s64 )hdc3020_thresh_get_hum (thresh ) * 1000000 ;
581594 /*
582- * Units of s_val are in micro percent, scale by 65535
583- * to get same units as s_thresh.
595+ * Units of s_val are in micro percent, scale by
596+ * HDC3020_THRESH_FRACTION to get same units as s_thresh.
584597 */
585- s_hyst = (s64 )s_val * 65535 ;
598+ s_hyst = (s64 )s_val * HDC3020_THRESH_FRACTION ;
586599 s_clr = hdc3020_thresh_clr (s_thresh , s_hyst , dir );
587600 s_clr = max (s_clr , 0 );
588601 s_clr = min (s_clr , HDC3020_MAX_HUM_MICRO );
@@ -630,39 +643,39 @@ static int hdc3020_read_thresh(struct iio_dev *indio_dev,
630643 thresh = hdc3020_thresh_get_temp (ret );
631644 switch (info ) {
632645 case IIO_EV_INFO_VALUE :
633- * val = thresh ;
646+ * val = thresh * MILLI ;
634647 break ;
635648 case IIO_EV_INFO_HYSTERESIS :
636649 ret = hdc3020_read_be16 (data , reg_clr );
637650 if (ret < 0 )
638651 return ret ;
639652
640653 clr = hdc3020_thresh_get_temp (ret );
641- * val = abs (thresh - clr );
654+ * val = abs (thresh - clr ) * MILLI ;
642655 break ;
643656 default :
644657 return - EOPNOTSUPP ;
645658 }
646- * val2 = 65535 ;
659+ * val2 = HDC3020_THRESH_FRACTION ;
647660 return IIO_VAL_FRACTIONAL ;
648661 case IIO_HUMIDITYRELATIVE :
649662 thresh = hdc3020_thresh_get_hum (ret );
650663 switch (info ) {
651664 case IIO_EV_INFO_VALUE :
652- * val = thresh ;
665+ * val = thresh * MILLI ;
653666 break ;
654667 case IIO_EV_INFO_HYSTERESIS :
655668 ret = hdc3020_read_be16 (data , reg_clr );
656669 if (ret < 0 )
657670 return ret ;
658671
659672 clr = hdc3020_thresh_get_hum (ret );
660- * val = abs (thresh - clr );
673+ * val = abs (thresh - clr ) * MILLI ;
661674 break ;
662675 default :
663676 return - EOPNOTSUPP ;
664677 }
665- * val2 = 65535 ;
678+ * val2 = HDC3020_THRESH_FRACTION ;
666679 return IIO_VAL_FRACTIONAL ;
667680 default :
668681 return - EOPNOTSUPP ;
0 commit comments