ds248x: add support for DS2482-800 in addition to DS2482-100 (#13)

pull/18/head v3.6.10
Audrius Paskevicius 5 years ago committed by GitHub
parent 8249b953cd
commit 764682acfd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -33,6 +33,14 @@ func ConvertAll(o onewire.Bus, maxResolutionBits int) error {
return nil return nil
} }
// StartAll starts a conversion on all DS18B20 devices on the bus.
// Similar to ConvertAll but returns without waiting for conversion to finish.
// To be used in conjunction with LastTemp() function. Conversion timing must be
// handled by other means.
func StartAll(o onewire.Bus) error {
return o.Tx([]byte{0xcc, 0x44}, nil, onewire.StrongPullup)
}
// New returns an object that communicates over 1-wire to the DS18B20 sensor // New returns an object that communicates over 1-wire to the DS18B20 sensor
// with the specified 64-bit address. // with the specified 64-bit address.
// //

@ -5,6 +5,7 @@
package ds248x package ds248x
import ( import (
"bytes"
"errors" "errors"
"fmt" "fmt"
"sync" "sync"
@ -15,6 +16,15 @@ import (
"periph.io/x/conn/v3/onewire" "periph.io/x/conn/v3/onewire"
) )
// DS248xType for chip connected to the system identification (ds2482-100, ds2482-800, ds2483).
type ds248xType uint8
const (
isDS2482x100 ds248xType = iota // DS2482-100 selected
isDS2482x800 // DS2482-800 selected
isDS2483 // DS2483 selected
)
// PupOhm controls the strength of the passive pull-up resistor // PupOhm controls the strength of the passive pull-up resistor
// on the 1-wire data line. The default value is 1000Ω. // on the 1-wire data line. The default value is 1000Ω.
type PupOhm uint8 type PupOhm uint8
@ -84,7 +94,7 @@ func New(i i2c.Bus, addr uint16, opts *Opts) (*Dev, error) {
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
isDS2483 bool // true: ds2483, false: ds2482-100 isDS248x ds248xType // 0: ds2482-100 1: ds2482-800 2: ds2483,
confReg byte // value written to configuration register confReg byte // value written to configuration register
tReset time.Duration // time to perform a 1-wire reset tReset time.Duration // time to perform a 1-wire reset
tSlot time.Duration // time to perform a 1-bit 1-wire read/write tSlot time.Duration // time to perform a 1-bit 1-wire read/write
@ -92,10 +102,16 @@ type Dev struct {
} }
func (d *Dev) String() string { func (d *Dev) String() string {
if d.isDS2483 { switch d.isDS248x {
case isDS2482x100:
return fmt.Sprintf("DS2482-100{%s}", d.i2c)
case isDS2482x800:
return fmt.Sprintf("DS2482-800{%s}", d.i2c)
case isDS2483:
return fmt.Sprintf("DS2483{%s}", d.i2c) return fmt.Sprintf("DS2483{%s}", d.i2c)
default:
return fmt.Sprintf("Undefined{%s}", d.i2c)
} }
return fmt.Sprintf("DS2482-100{%s}", d.i2c)
} }
// Halt implements conn.Resource. // Halt implements conn.Resource.
@ -154,6 +170,55 @@ func (d *Dev) Search(alarmOnly bool) ([]onewire.Address, error) {
return onewire.Search(d, alarmOnly) return onewire.Search(d, alarmOnly)
} }
// ChannelSelect function is for selecting one of eight 1-w channels on DS2482-800.
// On other chips it does nothing. Channel selection values are between
// 0 and 7. It is expected that application keeps track of
// with 1-w device is connected to with channel.
// Communication error is returned if present.
func (d *Dev) ChannelSelect(ch int) error {
switch d.isDS248x {
case isDS2482x800:
if ch < 0 || ch > 7 {
return fmt.Errorf("%s: channel out of range 0...7", d.String())
}
buf := []byte{cmdChannelSelect, cscw[ch]}
if err := d.i2c.Tx(buf, nil); err != nil {
return fmt.Errorf("%s: error: %s", d.String(), err)
}
return nil
case isDS2482x100, isDS2483:
if ch != 0 {
return fmt.Errorf("%s: invalid channel", d.String())
}
return nil
default:
return fmt.Errorf("ds248x: wrong chip")
}
}
// SelectedChannel function is to read with 1-w channel selected on DS2482-800.
// On other chips it always returns 0. It is expected that application keeps track of
// with 1-w device is connected to with channel.
// On error returns -1.
func (d *Dev) SelectedChannel() int {
switch d.isDS248x {
case isDS2482x800:
var sch [1]byte
if err := d.i2c.Tx([]byte{cmdSetReadPtr, regCSR}, sch[:]); err != nil {
return -1
}
ch := bytes.Index(cscr[:], sch[:])
if ch < 0 || ch > 7 {
return -1
}
return ch
case isDS2482x100, isDS2483:
return 0
default:
return -1
}
}
// SearchTriplet performs a single bit search triplet command on the bus, waits // SearchTriplet performs a single bit search triplet command on the bus, waits
// for it to complete and returs the outcome. // for it to complete and returs the outcome.
// //
@ -274,12 +339,10 @@ func (d *Dev) makeDev(opts *Opts) error {
} }
// Set the read ptr to the port configuration register to determine whether we have a // Set the read ptr to the port configuration register to determine whether we have a
// ds2483 vs ds2482-100. This will fail on devices that do not have a port config // ds2483 vs ds2482-100 or ds2482-800. This will fail on devices that do not have a port
// register, such as the ds2482-100. // configuration register, such as the ds2482-100 or ds2482-800.
d.isDS2483 = d.i2c.Tx([]byte{cmdSetReadPtr, regPCR}, nil) == nil if d.i2c.Tx([]byte{cmdSetReadPtr, regPCR}, nil) == nil {
d.isDS248x = isDS2483
// Set the options for the ds2483.
if d.isDS2483 {
buf := []byte{cmdAdjPort, buf := []byte{cmdAdjPort,
byte(0x00 + ((opts.ResetLow/time.Microsecond - 430) / 20 & 0x0f)), byte(0x00 + ((opts.ResetLow/time.Microsecond - 430) / 20 & 0x0f)),
byte(0x20 + ((opts.PresenceDetect/time.Microsecond - 55) / 2 & 0x0f)), byte(0x20 + ((opts.PresenceDetect/time.Microsecond - 55) / 2 & 0x0f)),
@ -290,13 +353,23 @@ func (d *Dev) makeDev(opts *Opts) error {
if err := d.i2c.Tx(buf, nil); err != nil { if err := d.i2c.Tx(buf, nil); err != nil {
return fmt.Errorf("ds248x: error while setting port config values: %s", err) return fmt.Errorf("ds248x: error while setting port config values: %s", err)
} }
} else {
// Set the read ptr to the channel selection register to determine whether we have a
// ds2482-800 vs ds2482-100. This will fail on devices that do not have a channel
// selection register, such as the ds2482-100.
if d.i2c.Tx([]byte{cmdSetReadPtr, regCSR}, nil) == nil {
d.isDS248x = isDS2482x800
buf := []byte{cmdChannelSelect, cscIO0w}
if err := d.i2c.Tx(buf, nil); err != nil {
return fmt.Errorf("ds2482-800: error while selecting channel: %s", err)
}
} else {
d.isDS248x = isDS2482x100
}
} }
return nil return nil
} }
//
// shortedBusError implements error and onewire.ShortedBusError. // shortedBusError implements error and onewire.ShortedBusError.
type shortedBusError string type shortedBusError string
@ -318,7 +391,8 @@ const (
cmdReset = 0xf0 // reset ds248x cmdReset = 0xf0 // reset ds248x
cmdSetReadPtr = 0xe1 // set the read pointer cmdSetReadPtr = 0xe1 // set the read pointer
cmdWriteConfig = 0xd2 // write the device configuration cmdWriteConfig = 0xd2 // write the device configuration
cmdAdjPort = 0xc3 // adjust 1-wire port cmdAdjPort = 0xc3 // adjust 1-wire port (ds2483)
cmdChannelSelect = 0xc3 // channel select (ds2482-800)
cmd1WReset = 0xb4 // reset the 1-wire bus cmd1WReset = 0xb4 // reset the 1-wire bus
cmd1WBit = 0x87 // perform a single-bit transaction on the 1-wire bus cmd1WBit = 0x87 // perform a single-bit transaction on the 1-wire bus
cmd1WWrite = 0xa5 // perform a byte write on the 1-wire bus cmd1WWrite = 0xa5 // perform a byte write on the 1-wire bus
@ -329,4 +403,26 @@ const (
regStatus = 0xf0 // read ptr for status register regStatus = 0xf0 // read ptr for status register
regRDR = 0xe1 // read ptr for read-data register regRDR = 0xe1 // read ptr for read-data register
regPCR = 0xb4 // read ptr for port configuration register regPCR = 0xb4 // read ptr for port configuration register
regCSR = 0xd2 // read ptr for channel selection register
// ds2482-800 channel selection codes to be written and read back
cscIO0w = 0xF0 // channel 0 writing
cscIO0r = 0xB8 // channel 0 reading
cscIO1w = 0xE1 // channel 1 writing
cscIO1r = 0xB1 // channel 1 reading
cscIO2w = 0xD2 // channel 2 writing
cscIO2r = 0xAA // channel 2 reading
cscIO3w = 0xC3 // channel 3 writing
cscIO3r = 0xA3 // channel 3 reading
cscIO4w = 0xB4 // channel 4 writing
cscIO4r = 0x9C // channel 4 reading
cscIO5w = 0xA5 // channel 5 writing
cscIO5r = 0x95 // channel 5 reading
cscIO6w = 0x96 // channel 6 writing
cscIO6r = 0x8E // channel 6 reading
cscIO7w = 0x87 // channel 7 writing
cscIO7r = 0x87 // channel 7 reading
) )
var cscw = [...]byte{cscIO0w, cscIO1w, cscIO2w, cscIO3w, cscIO4w, cscIO5w, cscIO6w, cscIO7w}
var cscr = [...]byte{cscIO0r, cscIO1r, cscIO2r, cscIO3r, cscIO4r, cscIO5r, cscIO6r, cscIO7r}

@ -11,23 +11,53 @@ import (
"periph.io/x/conn/v3/i2c/i2ctest" "periph.io/x/conn/v3/i2c/i2ctest"
) )
func TestNew(t *testing.T) { // Testing function New for DS2483.
func TestNew_DS2483(t *testing.T) {
bus := i2ctest.Playback{ bus := i2ctest.Playback{
DontPanic: true,
Ops: []i2ctest.IO{ Ops: []i2ctest.IO{
{Addr: 0x18, W: []byte{0xf0}}, {Addr: 0x18, W: []byte{0xf0}},
{Addr: 0x18, W: []byte{0xe1, 0xf0}, R: []byte{0x18}}, {Addr: 0x18, W: []byte{0xe1, 0xf0}, R: []byte{0x18}},
{Addr: 0x18, W: []byte{0xd2, 0xe1}, R: []byte{0x1}}, {Addr: 0x18, W: []byte{0xd2, 0xe1}, R: []byte{0x1}},
{Addr: 0x18, W: []byte{0xe1, 0xb4}}, {Addr: 0x18, W: []byte{0xe1, 0xb4}}, // (DS2483 ptr for port configuration register)
{Addr: 0x18, W: []byte{0xc3, 0x6, 0x26, 0x46, 0x66, 0x86}}, {Addr: 0x18, W: []byte{0xc3, 0x6, 0x26, 0x46, 0x66, 0x86}}, // (DS2483)
}, },
} }
d, err := New(&bus, 0x18, &DefaultOpts) d, err := New(&bus, 0x18, &DefaultOpts)
if s := d.String(); s != "DS2483{playback(24)}" {
t.Fatal(s)
}
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }
if s := d.String(); s != "DS2483{playback(24)}" {
if err := d.Halt(); err != nil {
t.Fatal(err)
}
if err := bus.Close(); err != nil {
t.Fatal(err)
}
}
// Testing function New for DS2482-800.
func TestNew_DS2482x800(t *testing.T) {
bus := i2ctest.Playback{
DontPanic: true,
Ops: []i2ctest.IO{
{Addr: 0x18, W: []byte{0xf0}},
{Addr: 0x18, W: []byte{0xe1, 0xf0}, R: []byte{0x18}},
{Addr: 0x18, W: []byte{0xd2, 0xe1}, R: []byte{0x1}},
{Addr: 0x18, W: []byte{0xe1, 0xd2}}, // (DS2482-800 ptr for channel selection register)
{Addr: 0x18, W: []byte{0xc3, 0xf0}}, // (DS2482-800)
},
}
d, err := New(&bus, 0x18, &DefaultOpts)
if s := d.String(); s != "DS2482-800{playback(24)}" {
t.Fatal(s) t.Fatal(s)
} }
if err != nil {
t.Fatal(err)
}
if err := d.Halt(); err != nil { if err := d.Halt(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -36,17 +66,24 @@ func TestNew(t *testing.T) {
} }
} }
func TestNew_opts(t *testing.T) { // Testing function New for DS2482-100.
func TestNew_DS2482x100(t *testing.T) {
bus := i2ctest.Playback{ bus := i2ctest.Playback{
DontPanic: true,
Ops: []i2ctest.IO{ Ops: []i2ctest.IO{
{Addr: 0x18, W: []byte{0xf0}}, {Addr: 0x18, W: []byte{0xf0}},
{Addr: 0x18, W: []byte{0xe1, 0xf0}, R: []byte{0x18}}, {Addr: 0x18, W: []byte{0xe1, 0xf0}, R: []byte{0x18}},
{Addr: 0x18, W: []byte{0xd2, 0xe1}, R: []byte{0x1}}, {Addr: 0x18, W: []byte{0xd2, 0xe1}, R: []byte{0x1}},
{Addr: 0x18, W: []byte{0xe1, 0xb4}},
{Addr: 0x18, W: []byte{0xc3, 0x6, 0x26, 0x46, 0x66, 0x86}},
}, },
} }
if _, err := New(&bus, 0x18, &DefaultOpts); err != nil { d, err := New(&bus, 0x18, &DefaultOpts)
if s := d.String(); s != "DS2482-100{playback(24)}" {
t.Fatal(s)
}
if err != nil {
t.Fatal(err)
}
if err := d.Halt(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
if err := bus.Close(); err != nil { if err := bus.Close(); err != nil {

Loading…
Cancel
Save