This repository has been archived by the owner on Sep 20, 2023. It is now read-only.
/
i2c.go
135 lines (119 loc) · 3.67 KB
/
i2c.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Copyright 2016 The Periph Authors. All rights reserved.
// Use of this source code is governed under the Apache License, Version 2.0
// that can be found in the LICENSE file.
// Package i2c defines the API to communicate with devices over the I²C
// protocol.
//
// As described in https://periph.io/x/periph/conn#hdr-Concepts, periph.io uses
// the concepts of Bus, Port and Conn.
//
// In the package i2c, 'Port' is not exposed, since once you know the I²C
// device address, there's no unconfigured Port to configure.
//
// Instead, the package includes the adapter 'Dev' to directly convert an I²C
// bus 'i2c.Bus' into a connection 'conn.Conn' by only specifying the device
// I²C address.
//
// See https://en.wikipedia.org/wiki/I%C2%B2C for more information.
package i2c
import (
"errors"
"io"
"strconv"
"periph.io/x/periph/conn"
"periph.io/x/periph/conn/gpio"
"periph.io/x/periph/conn/physic"
)
// Bus defines the interface a concrete I²C driver must implement.
//
// This interface is consummed by a device driver for a device sitting on a bus.
//
// This interface doesn't implement conn.Conn since a device address must be
// specified. Use i2cdev.Dev as an adapter to get a conn.Conn compatible
// object.
type Bus interface {
String() string
// Tx does a transaction at the specified device address.
//
// Write is done first, then read. One of 'w' or 'r' can be omitted for a
// unidirectional operation.
Tx(addr uint16, w, r []byte) error
// SetSpeed changes the bus speed, if supported.
//
// On linux due to the way the I²C sysfs driver is exposed in userland,
// calling this function will likely affect *all* I²C buses on the host.
SetSpeed(f physic.Frequency) error
}
// BusCloser is an I²C bus that can be closed.
//
// This interface is meant to be handled by the application and not the device
// driver. A device driver doesn't "own" a bus, hence it must operate on a Bus,
// not a BusCloser.
type BusCloser interface {
io.Closer
Bus
}
// Pins defines the pins that an I²C bus interconnect is using on the host.
//
// It is expected that a implementer of Bus also implement Pins but this is not
// a requirement.
type Pins interface {
// SCL returns the CLK (clock) pin.
SCL() gpio.PinIO
// SDA returns the DATA pin.
SDA() gpio.PinIO
}
// Dev is a device on a I²C bus.
//
// It implements conn.Conn.
//
// It saves from repeatedly specifying the device address.
type Dev struct {
Bus Bus
Addr uint16
}
func (d *Dev) String() string {
s := "<nil>"
if d.Bus != nil {
s = d.Bus.String()
}
return s + "(" + strconv.Itoa(int(d.Addr)) + ")"
}
// Tx does a transaction by adding the device's address to each command.
//
// It's a wrapper for Bus.Tx().
func (d *Dev) Tx(w, r []byte) error {
return d.Bus.Tx(d.Addr, w, r)
}
// Write writes to the I²C bus without reading, implementing io.Writer.
//
// It's a wrapper for Tx()
func (d *Dev) Write(b []byte) (int, error) {
if err := d.Tx(b, nil); err != nil {
return 0, err
}
return len(b), nil
}
// Duplex always return conn.Half for I²C.
func (d *Dev) Duplex() conn.Duplex {
return conn.Half
}
// Addr is an I²C slave address.
type Addr uint16
// Set sets the Addr to a value represented by the string s. Values maybe in
// decimal or hexadecimal form. Set implements the flag.Value interface.
func (a *Addr) Set(s string) error {
// Allow for only maximum of 10 bits for i2c addresses.
u, err := strconv.ParseUint(s, 0, 10)
if err != nil {
return errI2CSetError
}
*a = Addr(u)
return nil
}
// String returns an i2c.Addr as a string formated in hexadecimal.
func (a Addr) String() string {
return "0x" + strconv.FormatInt(int64(a), 16)
}
var errI2CSetError = errors.New("invalid i2c address")
var _ conn.Conn = &Dev{}