Minor cleanups in ds18b20 and ds248x.

Breaking change: removed ds248x.Dev.Close() as it doesn't 'own' anything.
Wrap comments at 80 cols.
Call Playback.Close(), removed extraneous Ops.
Slightly increased coverage.
pull/1/head
Marc-Antoine Ruel 9 years ago
parent daad425c63
commit 2e0e8d4ee9

@ -5,20 +5,28 @@
package ds18b20 package ds18b20
import ( import (
"os"
"testing" "testing"
"time" "time"
"periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire"
"periph.io/x/periph/conn/onewire/onewiretest" "periph.io/x/periph/conn/onewire/onewiretest"
"periph.io/x/periph/devices" "periph.io/x/periph/devices"
"periph.io/x/periph/host"
) )
// TestMain lets periph load all drivers and then runs the tests. func TestNew_resolution(t *testing.T) {
func TestMain(m *testing.M) { bus := &onewiretest.Playback{}
host.Init() var addr onewire.Address = 0x740000070e41ac28
os.Exit(m.Run()) if d, err := New(bus, addr, 1); d != nil || err == nil {
t.Fatal("invalid resolution")
}
}
func TestNew_read(t *testing.T) {
bus := &onewiretest.Playback{DontPanic: true}
var addr onewire.Address = 0x740000070e41ac28
if d, err := New(bus, addr, 9); d != nil || err == nil {
t.Fatal("invalid resolution")
}
} }
// TestTemperature tests a temperature conversion on a ds18b20 using // TestTemperature tests a temperature conversion on a ds18b20 using
@ -27,20 +35,26 @@ func TestTemperature(t *testing.T) {
// set-up playback using the recording output. // set-up playback using the recording output.
ops := []onewiretest.IO{ ops := []onewiretest.IO{
// Match ROM + Read Scratchpad (init) // Match ROM + Read Scratchpad (init)
{Write: []uint8{0x55, 0x28, 0xac, 0x41, 0xe, 0x7, 0x0, 0x0, 0x74, 0xbe}, {
Read: []uint8{0xe0, 0x1, 0x0, 0x0, 0x3f, 0xff, 0x10, 0x10, 0x3f}, Pull: false}, Write: []uint8{0x55, 0x28, 0xac, 0x41, 0xe, 0x7, 0x0, 0x0, 0x74, 0xbe},
Read: []uint8{0xe0, 0x1, 0x0, 0x0, 0x3f, 0xff, 0x10, 0x10, 0x3f},
},
// Match ROM + Convert // Match ROM + Convert
{Write: []uint8{0x55, 0x28, 0xac, 0x41, 0xe, 0x7, 0x0, 0x0, 0x74, 0x44}, {
Read: []uint8(nil), Pull: true}, Write: []uint8{0x55, 0x28, 0xac, 0x41, 0xe, 0x7, 0x0, 0x0, 0x74, 0x44},
Pull: true,
},
// Match ROM + Read Scratchpad (read temp) // Match ROM + Read Scratchpad (read temp)
{Write: []uint8{0x55, 0x28, 0xac, 0x41, 0xe, 0x7, 0x0, 0x0, 0x74, 0xbe}, {
Read: []uint8{0xe0, 0x1, 0x0, 0x0, 0x3f, 0xff, 0x10, 0x10, 0x3f}, Pull: false}, Write: []uint8{0x55, 0x28, 0xac, 0x41, 0xe, 0x7, 0x0, 0x0, 0x74, 0xbe},
Read: []uint8{0xe0, 0x1, 0x0, 0x0, 0x3f, 0xff, 0x10, 0x10, 0x3f},
},
} }
var addr onewire.Address = 0x740000070e41ac28 var addr onewire.Address = 0x740000070e41ac28
var temp devices.Celsius = 30000 // 30.000°C var temp devices.Celsius = 30000 // 30.000°C
owBus := &onewiretest.Playback{Ops: ops} bus := onewiretest.Playback{Ops: ops}
// Init the ds18b20. // Init the ds18b20.
ds18b20, err := New(owBus, addr, 10) ds18b20, err := New(&bus, addr, 10)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -59,6 +73,9 @@ func TestTemperature(t *testing.T) {
if dt < 188*time.Millisecond { if dt < 188*time.Millisecond {
t.Errorf("expected conversion to take >187ms, took %s", dt) t.Errorf("expected conversion to take >187ms, took %s", dt)
} }
if err := bus.Close(); err != nil {
t.Fatal(err)
}
} }
// TestConvertAll tests a temperature conversion on all ds18b20 using // TestConvertAll tests a temperature conversion on all ds18b20 using
@ -69,16 +86,33 @@ func TestConvertAll(t *testing.T) {
// Skip ROM + Convert // Skip ROM + Convert
{Write: []uint8{0xcc, 0x44}, Read: []uint8(nil), Pull: true}, {Write: []uint8{0xcc, 0x44}, Read: []uint8(nil), Pull: true},
} }
owBus := &onewiretest.Playback{Ops: ops} bus := onewiretest.Playback{Ops: ops}
// Perform the conversion // Perform the conversion
t0 := time.Now() t0 := time.Now()
if err := ConvertAll(owBus, 9); err != nil { if err := ConvertAll(&bus, 9); err != nil {
t.Fatal(err) t.Fatal(err)
} }
// Expect it to take >93ms // Expect it to take >93ms
if dt := time.Since(t0); dt < 94*time.Millisecond { if dt := time.Since(t0); dt < 94*time.Millisecond {
t.Errorf("expected conversion to take >93ms, took %s", dt) t.Errorf("expected conversion to take >93ms, took %s", dt)
} }
if err := bus.Close(); err != nil {
t.Fatal(err)
}
}
func TestConvertAll_resolution(t *testing.T) {
bus := &onewiretest.Playback{}
if err := ConvertAll(bus, 1); err == nil {
t.Fatal("invalid resolution")
}
}
func TestConvertAll_fail(t *testing.T) {
bus := &onewiretest.Playback{DontPanic: true}
if err := ConvertAll(bus, 9); err == nil {
t.Fatal("invalid resolution")
}
} }
/* Commented out in order not to import periph/host, need to move to smoke test /* Commented out in order not to import periph/host, need to move to smoke test

@ -13,15 +13,18 @@ import (
"periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire"
) )
// Dev is a handle to a ds248x device and it implements the onewire.Bus interface. // Dev is a handle to a ds248x device and it implements the onewire.Bus
// interface.
// //
// Dev implements a persistent error model: if a fatal error is encountered it places // Dev implements a persistent error model: if a fatal error is encountered it
// itself into an error state and immediately returns the last error on all subsequent // places itself into an error state and immediately returns the last error on
// calls. A fresh Dev, which reinitializes the hardware, must be created to proceed. // all subsequent calls. A fresh Dev, which reinitializes the hardware, must be
// created to proceed.
// //
// A persistent error is only set when there is a problem with the ds248x device itself // A persistent error is only set when there is a problem with the ds248x
// (or the I²C bus used to access it). Errors on the 1-wire bus do not cause persistent // device itself (or the I²C bus used to access it). Errors on the 1-wire bus
// errors and implement the onewire.BusError interface to indicate this fact. // do not cause persistent errors and implement the onewire.BusError interface
// to indicate this fact.
type Dev struct { type Dev struct {
sync.Mutex // lock for the bus while a transaction is in progress sync.Mutex // lock for the bus while a transaction is in progress
i2c conn.Conn // i2c device handle for the ds248x i2c conn.Conn // i2c device handle for the ds248x
@ -32,24 +35,16 @@ type Dev struct {
err error // persistent error, device will no longer operate err error // persistent error, device will no longer operate
} }
// String
func (d *Dev) String() string { func (d *Dev) String() string {
return fmt.Sprintf("ds248x") return "ds248x"
} }
// Close drops the I²C bus handle and sets a persistent error. // Tx performs a bus transaction, sending and receiving bytes, and ending by
func (d *Dev) Close() error { // pulling the bus high either weakly or strongly depending on the value of
d.i2c = nil // power.
d.err = fmt.Errorf("ds248x: invalid operation on closed bus")
return nil
}
// Tx performs a bus transaction, sending and receiving bytes, and
// ending by pulling the bus high either weakly or strongly depending
// on the value of power.
// //
// A strong pull-up is typically required to power temperature conversion // A strong pull-up is typically required to power temperature conversion or
// or EEPROM writes. // EEPROM writes.
func (d *Dev) Tx(w, r []byte, power onewire.Pullup) error { func (d *Dev) Tx(w, r []byte, power onewire.Pullup) error {
d.Lock() d.Lock()
defer d.Unlock() defer d.Unlock()
@ -85,9 +80,9 @@ func (d *Dev) Tx(w, r []byte, power onewire.Pullup) error {
return d.err return d.err
} }
// Search performs a "search" cycle on the 1-wire bus and returns the // Search performs a "search" cycle on the 1-wire bus and returns the addresses
// addresses of all devices on the bus if alarmOnly is false and of all // of all devices on the bus if alarmOnly is false and of all devices in alarm
// devices in alarm state if alarmOnly is true. // state if alarmOnly is true.
// //
// If an error occurs during the search the already-discovered devices are // If an error occurs during the search the already-discovered devices are
// returned with the error. // returned with the error.
@ -95,8 +90,8 @@ func (d *Dev) Search(alarmOnly bool) ([]onewire.Address, error) {
return onewire.Search(d, alarmOnly) return onewire.Search(d, alarmOnly)
} }
// SearchTriplet performs a single bit search triplet command on the bus, // SearchTriplet performs a single bit search triplet command on the bus, waits
// waits for it to complete and returs the outcome. // for it to complete and returs the outcome.
// //
// SearchTriplet should not be used directly, use Search instead. // SearchTriplet should not be used directly, use Search instead.
func (d *Dev) SearchTriplet(direction byte) (onewire.TripletResult, error) { func (d *Dev) SearchTriplet(direction byte) (onewire.TripletResult, error) {
@ -136,7 +131,8 @@ func (d *Dev) reset() (bool, error) {
return (status & 2) != 0, nil return (status & 2) != 0, nil
} }
// i2cTx is a helper function to call i2c.Tx and handle the error by persisting it. // i2cTx is a helper function to call i2c.Tx and handle the error by persisting
// it.
func (d *Dev) i2cTx(w, r []byte) { func (d *Dev) i2cTx(w, r []byte) {
if d.err != nil { if d.err != nil {
return return
@ -147,11 +143,11 @@ func (d *Dev) i2cTx(w, r []byte) {
// waitIdle waits for the one wire bus to be idle. // waitIdle waits for the one wire bus to be idle.
// //
// It initially sleeps for the delay and then polls the status register and // It initially sleeps for the delay and then polls the status register and
// sleeps for a tenth of the delay each time the status register indicates // sleeps for a tenth of the delay each time the status register indicates that
// that the bus is still busy. The last read status byte is returned. // the bus is still busy. The last read status byte is returned.
// //
// An overall timeout of 3ms is applied to the whole procedure. waitIdle // An overall timeout of 3ms is applied to the whole procedure. waitIdle uses
// uses the persistent error model and returns 0 if there is an error. // the persistent error model and returns 0 if there is an error.
func (d *Dev) waitIdle(delay time.Duration) byte { func (d *Dev) waitIdle(delay time.Duration) byte {
if d.err != nil { if d.err != nil {
return 0 return 0

@ -6,56 +6,79 @@ package ds248x
import ( import (
"fmt" "fmt"
"log"
"testing" "testing"
"periph.io/x/periph/conn/i2c/i2creg" "periph.io/x/periph/conn/i2c/i2creg"
"periph.io/x/periph/conn/i2c/i2ctest" "periph.io/x/periph/conn/i2c/i2ctest"
) )
// TestInit tests the initialization of a ds2483 using a recording.
func TestInit(t *testing.T) {
var ops = []i2ctest.IO{
{Addr: 0x18, Write: []byte{0xf0}, Read: []byte(nil)},
{Addr: 0x18, Write: []byte{0xe1, 0xf0}, Read: []byte{0x18}},
{Addr: 0x18, Write: []byte{0xd2, 0xe1}, Read: []byte{0x1}},
{Addr: 0x18, Write: []byte{0xe1, 0xb4}, Read: []byte(nil)},
{Addr: 0x18, Write: []byte{0xc3, 0x6, 0x26, 0x46, 0x66, 0x86}, Read: []byte(nil)},
{Addr: 0x18, Write: []byte{0x78, 0x0}, Read: []byte(nil)},
{Addr: 0x18, Write: []byte{}, Read: []byte{0xe8}},
}
bus := &i2ctest.Playback{Ops: ops}
if _, err := New(bus, nil); err != nil {
t.Fatal(err)
}
}
func Example() { func Example() {
// Open the I²C bus to which the DS248x is connected. // Open the I²C bus to which the DS248x is connected.
i2cBus, err := i2creg.Open("") i2cBus, err := i2creg.Open("")
if err != nil { if err != nil {
fmt.Println(err) log.Fatal(err)
return
} }
defer i2cBus.Close() defer i2cBus.Close()
// Open the DS248x to get a 1-wire bus. // Open the DS248x to get a 1-wire bus.
owBus, err := New(i2cBus, nil) owBus, err := New(i2cBus, nil)
if err != nil { if err != nil {
fmt.Println(err) log.Fatal(err)
return
} }
// Search devices on the bus // Search devices on the bus
devices, err := owBus.Search(false) devices, err := owBus.Search(false)
if err != nil { if err != nil {
fmt.Println(err) log.Fatal(err)
return
} }
fmt.Printf("Found %d 1-wire devices: ", len(devices)) fmt.Printf("Found %d 1-wire devices: ", len(devices))
for _, d := range devices { for _, d := range devices {
fmt.Printf(" %#16x", uint64(d)) fmt.Printf(" %#16x", uint64(d))
} }
fmt.Print('\n') fmt.Print("\n")
}
//
func TestNew(t *testing.T) {
bus := i2ctest.Playback{
Ops: []i2ctest.IO{
{Addr: 0x18, Write: []byte{0xf0}},
{Addr: 0x18, Write: []byte{0xe1, 0xf0}, Read: []byte{0x18}},
{Addr: 0x18, Write: []byte{0xd2, 0xe1}, Read: []byte{0x1}},
{Addr: 0x18, Write: []byte{0xe1, 0xb4}},
{Addr: 0x18, Write: []byte{0xc3, 0x6, 0x26, 0x46, 0x66, 0x86}},
},
}
d, err := New(&bus, nil)
if err != nil {
t.Fatal(err)
}
if s := d.String(); s != "ds248x" {
t.Fatal(s)
}
if err := bus.Close(); err != nil {
t.Fatal(err)
}
}
func TestNew_opts(t *testing.T) {
bus := i2ctest.Playback{
Ops: []i2ctest.IO{
{Addr: 0x18, Write: []byte{0xf0}},
{Addr: 0x18, Write: []byte{0xe1, 0xf0}, Read: []byte{0x18}},
{Addr: 0x18, Write: []byte{0xd2, 0xe1}, Read: []byte{0x1}},
{Addr: 0x18, Write: []byte{0xe1, 0xb4}},
{Addr: 0x18, Write: []byte{0xc3, 0x6, 0x26, 0x46, 0x66, 0x86}},
},
}
opts := &Opts{Addr: 0x18}
if _, err := New(&bus, opts); err != nil {
t.Fatal(err)
}
if err := bus.Close(); err != nil {
t.Fatal(err)
}
} }
/* Commented out in order not to import periph/host, need to move to smoke test /* Commented out in order not to import periph/host, need to move to smoke test

Loading…
Cancel
Save