summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorAlexander Yurchenko <grange@cvs.openbsd.org>2006-12-20 14:47:00 +0000
committerAlexander Yurchenko <grange@cvs.openbsd.org>2006-12-20 14:47:00 +0000
commitc40a742c0f3c3fcde40e94a1b2e579823acb07e3 (patch)
tree395c74adda6a229ffa8e2b903d9ebc7f86ac0b23 /sys/dev
parent1b6bcdace1e102b6acd3c88f5d7fd1c6dbbb6f09 (diff)
Implement high resolution temperature measuring.
Based on the diff provided by aaron@linville.org in PR 5314.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/onewire/owtemp.c33
1 files changed, 29 insertions, 4 deletions
diff --git a/sys/dev/onewire/owtemp.c b/sys/dev/onewire/owtemp.c
index 26ea09884c2..cd561a54c69 100644
--- a/sys/dev/onewire/owtemp.c
+++ b/sys/dev/onewire/owtemp.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: owtemp.c,v 1.4 2006/10/01 11:43:40 grange Exp $ */
+/* $OpenBSD: owtemp.c,v 1.5 2006/12/20 14:46:59 grange Exp $ */
/*
* Copyright (c) 2006 Alexander Yurchenko <grange@openbsd.org>
@@ -32,9 +32,19 @@
#include <dev/onewire/onewirereg.h>
#include <dev/onewire/onewirevar.h>
+/* Commands */
#define DS1920_CMD_CONVERT 0x44
#define DS1920_CMD_READ_SCRATCHPAD 0xbe
+/* Scratchpad layout */
+#define DS1920_SP_TEMP_LSB 0
+#define DS1920_SP_TEMP_MSB 1
+#define DS1920_SP_TH 2
+#define DS1920_SP_TL 3
+#define DS1920_SP_COUNT_REMAIN 6
+#define DS1920_SP_COUNT_PERC 7
+#define DS1920_SP_CRC 8
+
struct owtemp_softc {
struct device sc_dev;
@@ -124,6 +134,8 @@ owtemp_update(void *arg)
{
struct owtemp_softc *sc = arg;
u_int8_t data[9];
+ u_int16_t temp;
+ int count_perc, count_remain, val;
rw_enter_write(&sc->sc_lock);
onewire_lock(sc->sc_onewire, 0);
@@ -151,9 +163,22 @@ owtemp_update(void *arg)
*/
onewire_write_byte(sc->sc_onewire, DS1920_CMD_READ_SCRATCHPAD);
onewire_read_block(sc->sc_onewire, data, 9);
- if (onewire_crc(data, 8) == data[8]) {
- sc->sc_sensor.value = 273150000 +
- (int)((u_int16_t)data[1] << 8 | data[0]) * 500000;
+ if (onewire_crc(data, 8) == data[DS1920_SP_CRC]) {
+ temp = data[DS1920_SP_TEMP_MSB] << 8 |
+ data[DS1920_SP_TEMP_LSB];
+ count_perc = data[DS1920_SP_COUNT_PERC];
+ count_remain = data[DS1920_SP_COUNT_REMAIN];
+
+ if (count_perc != 0) {
+ /* High resolution algorithm */
+ temp &= ~0x0001;
+ val = temp * 500000 - 250000 +
+ ((count_perc - count_remain) * 1000000) /
+ count_perc;
+ } else {
+ val = temp * 500000;
+ }
+ sc->sc_sensor.value = 273150000 + val;
}
done: