From ff89f66af273677c9fb3a13ae20e47a193aa74d6 Mon Sep 17 00:00:00 2001 From: Michael Traver Date: Wed, 3 Apr 2019 10:46:27 -0700 Subject: [PATCH] mcp9808: Simplify bits to temperature conversions (#404) - Converting the alert registers and the ambient temp register to a physic.Temperature can use the same procedure. Unify them and document why this is possible. - Use != instead of > for bit checks - Inline bitsToTemperature calls in SenseWithAlerts --- experimental/devices/mcp9808/mcp9808.go | 44 +++++++++----------- experimental/devices/mcp9808/mcp9808_test.go | 8 ++-- 2 files changed, 25 insertions(+), 27 deletions(-) diff --git a/experimental/devices/mcp9808/mcp9808.go b/experimental/devices/mcp9808/mcp9808.go index cb45c81..7c32201 100644 --- a/experimental/devices/mcp9808/mcp9808.go +++ b/experimental/devices/mcp9808/mcp9808.go @@ -182,36 +182,33 @@ func (d *Dev) SenseWithAlerts(lower, upper, critical physic.Temperature) (physic } // Check for Alerts. - if alertBits&0xe0 > 0 { + if alertBits&0xe0 != 0 { var as []Alert - if alertBits&0x80 > 0 { + if alertBits&0x80 != 0 { // Critical Alert bit set. crit, err := d.m.ReadUint16(critAlert) if err != nil { return t, nil, errReadCriticalAlert } - t := alertBitsToTemperature(crit) - as = append(as, Alert{"critical", t}) + as = append(as, Alert{"critical", bitsToTemperature(crit)}) } - if alertBits&0x40 > 0 { + if alertBits&0x40 != 0 { // Upper Alert bit set. upper, err := d.m.ReadUint16(upperAlert) if err != nil { return t, nil, errReadUpperAlert } - t := alertBitsToTemperature(upper) - as = append(as, Alert{"upper", t}) + as = append(as, Alert{"upper", bitsToTemperature(upper)}) } - if alertBits&0x20 > 0 { + if alertBits&0x20 != 0 { // Lower Alert bit set. lower, err := d.m.ReadUint16(lowerAlert) if err != nil { return t, nil, errReadLowerAlert } - t := alertBitsToTemperature(lower) - as = append(as, Alert{"lower", t}) + as = append(as, Alert{"lower", bitsToTemperature(lower)}) } return t, as, nil @@ -263,14 +260,8 @@ func (d *Dev) readTemperature() (physic.Temperature, uint8, error) { if err != nil { return 0, 0, errReadTemperature } - // Convert to physic.Temperature 0.0625°C per bit - t := physic.Temperature(tbits&0x0FFF) * 62500 * physic.MicroKelvin - if tbits&0x1000 > 0 { - // Check for sign bit. - t -= 256 * physic.Celsius - } - t += physic.ZeroCelsius - return t, uint8(tbits>>8) & 0xe0, nil + + return bitsToTemperature(tbits), uint8(tbits>>8) & 0xe0, nil } func (d *Dev) setResolution(r resolution) error { @@ -382,14 +373,19 @@ var ( errTooShortInterval = errors.New("too short interval for resolution") ) -func alertBitsToTemperature(b uint16) physic.Temperature { - b = (b >> 2) & 0x07FF - t := physic.Temperature(b&0x03FF) * 250 * physic.MilliKelvin - if b&0x400 > 0 { +// bitsToTemperature converts the given bits to a physic.Temperature, assuming the +// bit layout common to the ambient temperature register and the alert registers. +// This works for the alert registers because while they do not make use of the 2 +// least significant bits (i.e. they have resolution of 0.25°C vs. 0.0625°C for the +// ambient temp register) those 2 bits are always read as 0. See page 22 of the +// datasheet. +func bitsToTemperature(b uint16) physic.Temperature { + t := physic.Temperature(b&0x0fff) * 62500 * physic.MicroKelvin + if b&0x1000 != 0 { + // Account for sign bit. t -= 256 * physic.Celsius } - t += physic.ZeroCelsius - return t + return t + physic.ZeroCelsius } func alertTemperatureToBits(t physic.Temperature) (uint16, error) { diff --git a/experimental/devices/mcp9808/mcp9808_test.go b/experimental/devices/mcp9808/mcp9808_test.go index 96581ca..a2dac17 100644 --- a/experimental/devices/mcp9808/mcp9808_test.go +++ b/experimental/devices/mcp9808/mcp9808_test.go @@ -895,7 +895,7 @@ func TestDev_setLowerAlert(t *testing.T) { } } -func Test_alertBitsToTemperature(t *testing.T) { +func Test_bitsToTemperature(t *testing.T) { tests := []struct { name string bits uint16 @@ -903,14 +903,16 @@ func Test_alertBitsToTemperature(t *testing.T) { }{ {"0°C", 0x0000, physic.ZeroCelsius}, {"0.25°C", 0x0004, physic.ZeroCelsius + 250*physic.MilliKelvin}, + {"0.9375°C", 0x000f, physic.ZeroCelsius + 937500*physic.MicroKelvin}, + {"124.75°C", 0x07cc, physic.ZeroCelsius + 124750*physic.MilliKelvin}, // Negative values are in two's complement. See page 22 of the datasheet. {"-0.25°C", 0x1ffc, physic.ZeroCelsius - 250*physic.MilliKelvin}, {"-39.75°C", 0x1d84, physic.ZeroCelsius - 39750*physic.MilliKelvin}, } for _, tt := range tests { - if got := alertBitsToTemperature(tt.bits); got != tt.want { - t.Errorf("alertBitsToTemperature(%s) = %v, want %v", tt.name, got, tt.want) + if got := bitsToTemperature(tt.bits); got != tt.want { + t.Errorf("bitsToTemperature(%s) = %v, want %v", tt.name, got, tt.want) } } }