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/color"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/spi"
"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 _ fmt.Stringer = &Dev{}

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

@ -14,14 +14,9 @@ import (
// 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 {
// 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
}

@ -11,6 +11,7 @@ import (
"image/color"
"image/draw"
"periph.io/x/periph/conn"
"periph.io/x/periph/devices"
)
@ -23,7 +24,7 @@ func (d *Display) String() string {
return "Display"
}
// Halt implements devices.Device. It is a noop.
// Halt implements conn.Resource. It is a noop.
func (d *Display) Halt() error {
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)
}
var _ conn.Resource = &Display{}
var _ devices.Display = &Display{}
var _ devices.Device = &Display{}
var _ fmt.Stringer = &Display{}

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

@ -11,7 +11,6 @@ import (
"periph.io/x/periph/conn"
"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
@ -43,7 +42,7 @@ func (d *Dev) String() string {
return fmt.Sprintf("DS2482-100{%s}", d.i2c)
}
// Halt implements devices.Device.
// Halt implements conn.Resource.
func (d *Dev) Halt() error {
return nil
}
@ -197,5 +196,5 @@ type busError string
func (e busError) Error() string { return string(e) }
func (e busError) BusError() bool { return true }
var _ devices.Device = &Dev{}
var _ conn.Resource = &Dev{}
var _ fmt.Stringer = &Dev{}

@ -28,6 +28,7 @@ import (
"sync"
"time"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/i2c"
"periph.io/x/periph/conn/mmr"
"periph.io/x/periph/devices"
@ -150,14 +151,14 @@ type FFCMode struct {
//
// Maximum I²C speed is 1Mhz.
type Dev struct {
c conn
c cciConn
serial uint64
}
// New returns a driver for the FLIR Lepton CCI protocol.
func New(i i2c.Bus) (*Dev, error) {
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.
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
// via memory mapped registers.
type conn struct {
type cciConn struct {
mu sync.Mutex
r mmr.Dev16
}
func (c *conn) String() string {
func (c *cciConn) String() string {
return fmt.Sprintf("%s", &c.r)
}
// 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.
for {
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.
func (c *conn) get(cmd command, data interface{}) error {
func (c *cciConn) get(cmd command, data interface{}) error {
if data == 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.
func (c *conn) set(cmd command, data interface{}) error {
func (c *cciConn) set(cmd command, data interface{}) error {
if data == 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.
func (c *conn) run(cmd command) error {
func (c *cciConn) run(cmd command) error {
c.mu.Lock()
defer c.mu.Unlock()
if _, err := c.waitIdle(); err != nil {
@ -557,6 +558,6 @@ const (
// TODO(maruel): Enable RadXXX commands.
var _ devices.Device = &Dev{}
var _ conn.Resource = &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}},
}
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 {
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}},
}
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
if err := c.get(sysStatus, &v); err != nil {
t.Fatal(err)
@ -275,7 +275,7 @@ func TestConn_get(t *testing.T) {
for len(ops) != 0 {
ops = ops[:len(ops)-1]
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
if c.get(sysStatus, &v) == nil {
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)},
}
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)
if err := c.get(sysStatus, v); err != nil {
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}},
}
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
if c.get(sysStatus, &v) == nil {
t.Fatal("waitIdle failed")
@ -334,7 +334,7 @@ func TestConn_get_fail_waitidle(t *testing.T) {
func TestConn_get_fail(t *testing.T) {
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 {
t.Fatal("nil value")
}
@ -365,7 +365,7 @@ func TestConn_set(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}},
}
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
if err := c.set(sysStatus, &v); err != nil {
t.Fatal(err)
@ -378,7 +378,7 @@ func TestConn_set(t *testing.T) {
for len(ops) != 0 {
ops = ops[:len(ops)-1]
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
if c.set(sysStatus, &v) == nil {
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}},
}
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)
if err := c.set(sysStatus, v); err != nil {
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}},
}
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
if c.set(sysStatus, &v) == nil {
t.Fatal("waitIdle failed")
@ -439,7 +439,7 @@ func TestConn_set_fail_waitidle(t *testing.T) {
func TestConn_set_fail(t *testing.T) {
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 {
t.Fatal("nil value")
}
@ -465,7 +465,7 @@ func TestConn_run(t *testing.T) {
{Addr: 42, W: []byte{0x00, 0x02}, R: []byte{0x00, 0x06}},
}
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 {
t.Fatal(err)
}
@ -477,7 +477,7 @@ func TestConn_run(t *testing.T) {
for len(ops) != 0 {
ops = ops[:len(ops)-1]
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 {
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}},
}
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 {
t.Fatal("waitIdle failed")
}
@ -561,13 +561,13 @@ func TestStrings(t *testing.T) {
func getDev(ops []i2ctest.IO) (*i2ctest.Playback, *Dev) {
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
}
func getDevFail() *Dev {
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
}

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

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

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

Loading…
Cancel
Save