conn: Add Resource, superseds devices.Device (#162)

In practice I want to be able for gpioreg.Register() to eventually enforce that
Halt() is implemented on gpio.Pin, so that three's a consistent way to stop
gpiostream operations or PWM() output. This requires the interface to live in
conn, not in devices.

Do not use go1.9 type alias to not break compatibility with older Go version
yet.
pull/1/head
M-A 9 years ago committed by GitHub
parent 3d1aec5647
commit 7dc1026c65

@ -10,6 +10,7 @@ import (
"image" "image"
"image/color" "image/color"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/spi" "periph.io/x/periph/conn/spi"
"periph.io/x/periph/devices" "periph.io/x/periph/devices"
) )
@ -314,6 +315,6 @@ func New(p spi.Port, numPixels int, intensity uint8, temperature uint16) (*Dev,
// //
var _ devices.Device = &Dev{} var _ conn.Resource = &Dev{}
var _ devices.Display = &Dev{} var _ devices.Display = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -514,6 +514,6 @@ var defaults = Opts{
Humidity: O4x, Humidity: O4x,
} }
var _ conn.Resource = &Dev{}
var _ devices.Environmental = &Dev{} var _ devices.Environmental = &Dev{}
var _ devices.Device = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -14,14 +14,9 @@ import (
// Device is a basic device. // Device is a basic device.
// //
// It is expected to implement fmt.Stringer. // This interface is deprecated and will be removed in v3. Use conn.Resource
// instead.
type Device interface { type Device interface {
// Halt stops the device.
//
// Unlike a connection, a device cannot be closed, only the port can be
// closed. On the other hand, a device can be halted. What halting entails
// depends on the actual device but it should stop motion, sensing or light
// emission.
Halt() error Halt() error
} }

@ -11,6 +11,7 @@ import (
"image/color" "image/color"
"image/draw" "image/draw"
"periph.io/x/periph/conn"
"periph.io/x/periph/devices" "periph.io/x/periph/devices"
) )
@ -23,7 +24,7 @@ func (d *Display) String() string {
return "Display" return "Display"
} }
// Halt implements devices.Device. It is a noop. // Halt implements conn.Resource. It is a noop.
func (d *Display) Halt() error { func (d *Display) Halt() error {
return nil return nil
} }
@ -52,6 +53,6 @@ func (d *Display) Draw(r image.Rectangle, src image.Image, sp image.Point) {
draw.Draw(d.Img, r, src, sp, draw.Src) draw.Draw(d.Img, r, src, sp, draw.Src)
} }
var _ conn.Resource = &Display{}
var _ devices.Display = &Display{} var _ devices.Display = &Display{}
var _ devices.Device = &Display{}
var _ fmt.Stringer = &Display{} var _ fmt.Stringer = &Display{}

@ -26,6 +26,7 @@ import (
"fmt" "fmt"
"time" "time"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire"
"periph.io/x/periph/devices" "periph.io/x/periph/devices"
) )
@ -98,7 +99,7 @@ func (d *Dev) String() string {
return fmt.Sprintf("DS18B20{%v}", d.onewire) return fmt.Sprintf("DS18B20{%v}", d.onewire)
} }
// Halt implements devices.Device. // Halt implements conn.Resource.
func (d *Dev) Halt() error { func (d *Dev) Halt() error {
return nil return nil
} }
@ -174,5 +175,5 @@ func (d *Dev) readScratchpad() ([]byte, error) {
return spad[:8], nil return spad[:8], nil
} }
var _ devices.Device = &Dev{} var _ conn.Resource = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -11,7 +11,6 @@ import (
"periph.io/x/periph/conn" "periph.io/x/periph/conn"
"periph.io/x/periph/conn/onewire" "periph.io/x/periph/conn/onewire"
"periph.io/x/periph/devices"
) )
// Dev is a handle to a ds248x device and it implements the onewire.Bus // Dev is a handle to a ds248x device and it implements the onewire.Bus
@ -43,7 +42,7 @@ func (d *Dev) String() string {
return fmt.Sprintf("DS2482-100{%s}", d.i2c) return fmt.Sprintf("DS2482-100{%s}", d.i2c)
} }
// Halt implements devices.Device. // Halt implements conn.Resource.
func (d *Dev) Halt() error { func (d *Dev) Halt() error {
return nil return nil
} }
@ -197,5 +196,5 @@ type busError string
func (e busError) Error() string { return string(e) } func (e busError) Error() string { return string(e) }
func (e busError) BusError() bool { return true } func (e busError) BusError() bool { return true }
var _ devices.Device = &Dev{} var _ conn.Resource = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -28,6 +28,7 @@ import (
"sync" "sync"
"time" "time"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/i2c" "periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/mmr" "periph.io/x/periph/conn/mmr"
"periph.io/x/periph/devices" "periph.io/x/periph/devices"
@ -150,14 +151,14 @@ type FFCMode struct {
// //
// Maximum I²C speed is 1Mhz. // Maximum I²C speed is 1Mhz.
type Dev struct { type Dev struct {
c conn c cciConn
serial uint64 serial uint64
} }
// New returns a driver for the FLIR Lepton CCI protocol. // New returns a driver for the FLIR Lepton CCI protocol.
func New(i i2c.Bus) (*Dev, error) { func New(i i2c.Bus) (*Dev, error) {
d := &Dev{ d := &Dev{
c: conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: i, Addr: 0x2A}, Order: internal.Big16}}, c: cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: i, Addr: 0x2A}, Order: internal.Big16}},
} }
// Wait for the device to be booted. // Wait for the device to be booted.
for { for {
@ -313,21 +314,21 @@ func (d *Dev) RunFFC() error {
// //
// conn is the low level connection. // cciConn is the low level connection.
// //
// It implements the low level protocol to run the GET, SET and RUN commands // It implements the low level protocol to run the GET, SET and RUN commands
// via memory mapped registers. // via memory mapped registers.
type conn struct { type cciConn struct {
mu sync.Mutex mu sync.Mutex
r mmr.Dev16 r mmr.Dev16
} }
func (c *conn) String() string { func (c *cciConn) String() string {
return fmt.Sprintf("%s", &c.r) return fmt.Sprintf("%s", &c.r)
} }
// waitIdle waits for the busy bit to clear. // waitIdle waits for the busy bit to clear.
func (c *conn) waitIdle() (StatusBit, error) { func (c *cciConn) waitIdle() (StatusBit, error) {
// Do not take the lock. // Do not take the lock.
for { for {
if s, err := c.r.ReadUint16(regStatus); err != nil || StatusBit(s)&StatusBusy == 0 { if s, err := c.r.ReadUint16(regStatus); err != nil || StatusBit(s)&StatusBusy == 0 {
@ -338,7 +339,7 @@ func (c *conn) waitIdle() (StatusBit, error) {
} }
// get returns an attribute by querying the device. // get returns an attribute by querying the device.
func (c *conn) get(cmd command, data interface{}) error { func (c *cciConn) get(cmd command, data interface{}) error {
if data == nil { if data == nil {
return errors.New("lepton-cci: get() argument must not be nil") return errors.New("lepton-cci: get() argument must not be nil")
} }
@ -393,7 +394,7 @@ func (c *conn) get(cmd command, data interface{}) error {
} }
// set returns an attribute on the device. // set returns an attribute on the device.
func (c *conn) set(cmd command, data interface{}) error { func (c *cciConn) set(cmd command, data interface{}) error {
if data == nil { if data == nil {
return errors.New("lepton-cci: set() argument must not be nil") return errors.New("lepton-cci: set() argument must not be nil")
} }
@ -437,7 +438,7 @@ func (c *conn) set(cmd command, data interface{}) error {
} }
// run runs a command on the device that doesn't need any argument. // run runs a command on the device that doesn't need any argument.
func (c *conn) run(cmd command) error { func (c *cciConn) run(cmd command) error {
c.mu.Lock() c.mu.Lock()
defer c.mu.Unlock() defer c.mu.Unlock()
if _, err := c.waitIdle(); err != nil { if _, err := c.waitIdle(); err != nil {
@ -557,6 +558,6 @@ const (
// TODO(maruel): Enable RadXXX commands. // TODO(maruel): Enable RadXXX commands.
var _ devices.Device = &Dev{} var _ conn.Resource = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}
var _ fmt.Stringer = &conn{} var _ fmt.Stringer = &cciConn{}

@ -105,7 +105,7 @@ func TestWaitIdle(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
d := Dev{c: conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}} d := Dev{c: cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}}
if _, err := d.WaitIdle(); err != nil { if _, err := d.WaitIdle(); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -262,7 +262,7 @@ func TestConn_get(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x08}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}}, {Addr: 42, W: []byte{0x00, 0x08}, R: []byte{0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
var v internal.Status var v internal.Status
if err := c.get(sysStatus, &v); err != nil { if err := c.get(sysStatus, &v); err != nil {
t.Fatal(err) t.Fatal(err)
@ -275,7 +275,7 @@ func TestConn_get(t *testing.T) {
for len(ops) != 0 { for len(ops) != 0 {
ops = ops[:len(ops)-1] ops = ops[:len(ops)-1]
bus := i2ctest.Playback{Ops: ops, DontPanic: true} bus := i2ctest.Playback{Ops: ops, DontPanic: true}
c = conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c = cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
var v internal.Status var v internal.Status
if c.get(sysStatus, &v) == nil { if c.get(sysStatus, &v) == nil {
t.Fatal("should have failed") t.Fatal("should have failed")
@ -300,7 +300,7 @@ func TestConn_get_large(t *testing.T) {
{Addr: 42, W: []byte{0xf8, 0}, R: make([]byte, 2048)}, {Addr: 42, W: []byte{0xf8, 0}, R: make([]byte, 2048)},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
v := make([]byte, 2048) v := make([]byte, 2048)
if err := c.get(sysStatus, v); err != nil { if err := c.get(sysStatus, v); err != nil {
t.Fatal(err) t.Fatal(err)
@ -322,7 +322,7 @@ func TestConn_get_fail_waitidle(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x01, 0x00}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x01, 0x00}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
var v internal.Status var v internal.Status
if c.get(sysStatus, &v) == nil { if c.get(sysStatus, &v) == nil {
t.Fatal("waitIdle failed") t.Fatal("waitIdle failed")
@ -334,7 +334,7 @@ func TestConn_get_fail_waitidle(t *testing.T) {
func TestConn_get_fail(t *testing.T) { func TestConn_get_fail(t *testing.T) {
bus := i2ctest.Playback{} bus := i2ctest.Playback{}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
if c.get(sysStatus, nil) == nil { if c.get(sysStatus, nil) == nil {
t.Fatal("nil value") t.Fatal("nil value")
} }
@ -365,7 +365,7 @@ func TestConn_set(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
var v internal.Status var v internal.Status
if err := c.set(sysStatus, &v); err != nil { if err := c.set(sysStatus, &v); err != nil {
t.Fatal(err) t.Fatal(err)
@ -378,7 +378,7 @@ func TestConn_set(t *testing.T) {
for len(ops) != 0 { for len(ops) != 0 {
ops = ops[:len(ops)-1] ops = ops[:len(ops)-1]
bus := i2ctest.Playback{Ops: ops, DontPanic: true} bus := i2ctest.Playback{Ops: ops, DontPanic: true}
c = conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c = cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
var v internal.Status var v internal.Status
if c.set(sysStatus, &v) == nil { if c.set(sysStatus, &v) == nil {
t.Fatal("should have failed") t.Fatal("should have failed")
@ -403,7 +403,7 @@ func TestConn_set_large(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
v := make([]byte, 2048) v := make([]byte, 2048)
if err := c.set(sysStatus, v); err != nil { if err := c.set(sysStatus, v); err != nil {
t.Fatal(err) t.Fatal(err)
@ -427,7 +427,7 @@ func TestConn_set_fail_waitidle(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x0f, 0x00}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x0f, 0x00}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
var v internal.Status var v internal.Status
if c.set(sysStatus, &v) == nil { if c.set(sysStatus, &v) == nil {
t.Fatal("waitIdle failed") t.Fatal("waitIdle failed")
@ -439,7 +439,7 @@ func TestConn_set_fail_waitidle(t *testing.T) {
func TestConn_set_fail(t *testing.T) { func TestConn_set_fail(t *testing.T) {
bus := i2ctest.Playback{} bus := i2ctest.Playback{}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
if c.set(sysStatus, nil) == nil { if c.set(sysStatus, nil) == nil {
t.Fatal("nil value") t.Fatal("nil value")
} }
@ -465,7 +465,7 @@ func TestConn_run(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
if err := c.run(sysFCCRunNormalization); err != nil { if err := c.run(sysFCCRunNormalization); err != nil {
t.Fatal(err) t.Fatal(err)
} }
@ -477,7 +477,7 @@ func TestConn_run(t *testing.T) {
for len(ops) != 0 { for len(ops) != 0 {
ops = ops[:len(ops)-1] ops = ops[:len(ops)-1]
bus := i2ctest.Playback{Ops: ops, DontPanic: true} bus := i2ctest.Playback{Ops: ops, DontPanic: true}
c = conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c = cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
if c.run(sysFCCRunNormalization) == nil { if c.run(sysFCCRunNormalization) == nil {
t.Fatal("should have failed") t.Fatal("should have failed")
} }
@ -499,7 +499,7 @@ func TestConn_run_fail_waitidle(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x0f, 0x00}}, {Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x0f, 0x00}},
} }
bus := i2ctest.Playback{Ops: ops} bus := i2ctest.Playback{Ops: ops}
c := conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}} c := cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: &bus, Addr: 0x2A}, Order: internal.Big16}}
if c.run(sysFCCRunNormalization) == nil { if c.run(sysFCCRunNormalization) == nil {
t.Fatal("waitIdle failed") t.Fatal("waitIdle failed")
} }
@ -561,13 +561,13 @@ func TestStrings(t *testing.T) {
func getDev(ops []i2ctest.IO) (*i2ctest.Playback, *Dev) { func getDev(ops []i2ctest.IO) (*i2ctest.Playback, *Dev) {
bus := &i2ctest.Playback{Ops: ops} bus := &i2ctest.Playback{Ops: ops}
d := &Dev{c: conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: bus, Addr: 0x2A}, Order: internal.Big16}}} d := &Dev{c: cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: bus, Addr: 0x2A}, Order: internal.Big16}}}
return bus, d return bus, d
} }
func getDevFail() *Dev { func getDevFail() *Dev {
bus := &i2ctest.Playback{DontPanic: true} bus := &i2ctest.Playback{DontPanic: true}
d := &Dev{c: conn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: bus, Addr: 0x2A}, Order: internal.Big16}}} d := &Dev{c: cciConn{r: mmr.Dev16{Conn: &i2c.Dev{Bus: bus, Addr: 0x2A}, Order: internal.Big16}}}
return d return d
} }

@ -454,5 +454,5 @@ func verifyCRC(d []byte) bool {
return internal.CRC16(tmp) == internal.Big16.Uint16(d[2:]) return internal.CRC16(tmp) == internal.Big16.Uint16(d[2:])
} }
var _ devices.Device = &Dev{} var _ conn.Resource = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -488,6 +488,6 @@ const (
i2cData = 0x40 // I²C transaction has stream of data bytes i2cData = 0x40 // I²C transaction has stream of data bytes
) )
var _ conn.Resource = &Dev{}
var _ devices.Display = &Dev{} var _ devices.Display = &Dev{}
var _ devices.Device = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

@ -15,8 +15,8 @@ import (
"runtime" "runtime"
"time" "time"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/gpio" "periph.io/x/periph/conn/gpio"
"periph.io/x/periph/devices"
"periph.io/x/periph/host/cpu" "periph.io/x/periph/host/cpu"
) )
@ -200,5 +200,5 @@ func (d *Dev) sleepHalfCycle() {
cpu.Nanospin(clockHalfCycle) cpu.Nanospin(clockHalfCycle)
} }
var _ devices.Device = &Dev{} var _ conn.Resource = &Dev{}
var _ fmt.Stringer = &Dev{} var _ fmt.Stringer = &Dev{}

Loading…
Cancel
Save