Skip to content

Commit

Permalink
Merge pull request #1 from googolgl/develop
Browse files Browse the repository at this point in the history
develop to master
  • Loading branch information
googolgl authored Jul 29, 2021
2 parents f439f96 + de689ad commit bc63eef
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 90 deletions.
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ Golang usage

```go
func main() {
// Create new connection to I2C bus on 2 line with address 0x27
i2cDevice, err := i2c.New(0x27, 2)
// Create new connection to I2C dev on /dev/i2c-0 with address 0x27
i2cDevice, err := i2c.New(0x27, "/dev/i2c-0")
if err != nil {
i2cDevice.Log.Fatal(err)
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
module github.com/googolgl/go-i2c

go 1.14
go 1.16

require github.com/sirupsen/logrus v1.6.0
require github.com/sirupsen/logrus v1.8.1
12 changes: 7 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE=
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037 h1:YyJpGZS1sBuBCzLAR1VEpK193GlqGZbnPFnPV/5Rsb4=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
150 changes: 73 additions & 77 deletions i2c.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ package i2c

import (
"encoding/hex"
"fmt"
"os"
"syscall"

Expand All @@ -20,7 +19,7 @@ import (
// Options represents a connection to I2C-device.
type Options struct {
addr uint8
bus int
dev string
rc *os.File
Log *logrus.Logger
}
Expand All @@ -30,74 +29,57 @@ type Options struct {
// supported as well: you should preliminary specify
// register address to read from, either write register
// together with the data in case of write operations.
func New(addr uint8, bus int) (*Options, error) {
v := &Options{
func New(addr uint8, dev string) (*Options, error) {
i2c := &Options{
addr: addr,
bus: bus,
dev: "/dev/i2c-0",
Log: logrus.New(),
}

f, err := os.OpenFile(fmt.Sprintf("/dev/i2c-%d", bus), os.O_RDWR, 0600)
if dev != "" {
i2c.dev = dev
}

f, err := os.OpenFile(dev, os.O_RDWR, 0600)
if err != nil {
return v, err
return i2c, err
}
if err := ioctl(f.Fd(), I2C_SLAVE, uintptr(addr)); err != nil {
return v, err
return i2c, err
}

v.rc = f
return v, nil
}

// GetBus return bus line, where I2C-device is allocated.
func (o *Options) GetBus() int {
return o.bus
i2c.rc = f
return i2c, nil
}

// GetAddr return device occupied address in the bus.
func (o *Options) GetAddr() uint8 {
return o.addr
}

func (o *Options) write(buf []byte) (int, error) {
return o.rc.Write(buf)
}

// WriteBytes send bytes to the remote I2C-device. The interpretation of
// the message is implementation-dependent.
func (o *Options) WriteBytes(buf []byte) (int, error) {
o.Log.Debugf("Write %d hex bytes: [%+v]", len(buf), hex.EncodeToString(buf))
return o.write(buf)
// GetDev return full device name.
func (o *Options) GetDev() string {
return o.dev
}

func (o *Options) read(buf []byte) (int, error) {
return o.rc.Read(buf)
}
// READ SECTION

// ReadBytes read bytes from I2C-device.
// Number of bytes read correspond to buf parameter length.
func (o *Options) ReadBytes(buf []byte) (int, error) {
n, err := o.read(buf)
n, err := o.rc.Read(buf)
if err != nil {
return n, err
}
o.Log.Debugf("Read %d hex bytes: [%+v]", len(buf), hex.EncodeToString(buf))
return n, nil
}

// Close I2C-connection.
func (o *Options) Close() error {
return o.rc.Close()
}

// ReadRegBytes read count of n byte's sequence from I2C-device
// starting from reg address.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) ReadRegBytes(reg byte, n int) ([]byte, int, error) {
o.Log.Debugf("Read %d bytes starting from reg 0x%0X...", n, reg)
_, err := o.WriteBytes([]byte{reg})
if err != nil {

if _, err := o.WriteBytes([]byte{reg}); err != nil {
return nil, 0, err
}
buf := make([]byte, n)
Expand All @@ -106,48 +88,29 @@ func (o *Options) ReadRegBytes(reg byte, n int) ([]byte, int, error) {
return nil, 0, err
}
return buf, c, nil

}

// ReadRegU8 reads byte from I2C-device register specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) ReadRegU8(reg byte) (byte, error) {
_, err := o.WriteBytes([]byte{reg})
if err != nil {
if _, err := o.WriteBytes([]byte{reg}); err != nil {
return 0, err
}
buf := make([]byte, 1)
_, err = o.ReadBytes(buf)
if err != nil {
if _, err := o.ReadBytes(buf); err != nil {
return 0, err
}
o.Log.Debugf("Read U8 %d from reg 0x%0X", buf[0], reg)
return buf[0], nil
}

// WriteRegU8 writes byte to I2C-device register specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) WriteRegU8(reg byte, value byte) error {
buf := []byte{reg, value}
_, err := o.WriteBytes(buf)
if err != nil {
return err
}
o.Log.Debugf("Write U8 %d to reg 0x%0X", value, reg)
return nil
}

// ReadRegU16BE reads unsigned big endian word (16 bits)
// from I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) ReadRegU16BE(reg byte) (uint16, error) {
_, err := o.WriteBytes([]byte{reg})
if err != nil {
if _, err := o.WriteBytes([]byte{reg}); err != nil {
return 0, err
}
buf := make([]byte, 2)
_, err = o.ReadBytes(buf)
if err != nil {
if _, err := o.ReadBytes(buf); err != nil {
return 0, err
}
w := uint16(buf[0])<<8 + uint16(buf[1])
Expand All @@ -157,7 +120,6 @@ func (o *Options) ReadRegU16BE(reg byte) (uint16, error) {

// ReadRegU16LE reads unsigned little endian word (16 bits)
// from I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) ReadRegU16LE(reg byte) (uint16, error) {
w, err := o.ReadRegU16BE(reg)
if err != nil {
Expand All @@ -170,15 +132,12 @@ func (o *Options) ReadRegU16LE(reg byte) (uint16, error) {

// ReadRegS16BE reads signed big endian word (16 bits)
// from I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) ReadRegS16BE(reg byte) (int16, error) {
_, err := o.WriteBytes([]byte{reg})
if err != nil {
if _, err := o.WriteBytes([]byte{reg}); err != nil {
return 0, err
}
buf := make([]byte, 2)
_, err = o.ReadBytes(buf)
if err != nil {
if _, err := o.ReadBytes(buf); err != nil {
return 0, err
}
w := int16(buf[0])<<8 + int16(buf[1])
Expand All @@ -188,7 +147,6 @@ func (o *Options) ReadRegS16BE(reg byte) (int16, error) {

// ReadRegS16LE reads signed little endian word (16 bits)
// from I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) ReadRegS16LE(reg byte) (int16, error) {
w, err := o.ReadRegS16BE(reg)
if err != nil {
Expand All @@ -197,16 +155,32 @@ func (o *Options) ReadRegS16LE(reg byte) (int16, error) {
// exchange bytes
w = (w&0xFF)<<8 + w>>8
return w, nil
}

// WRITE SECTION

// WriteBytes send bytes to the remote I2C-device. The interpretation of
// the message is implementation-dependent.
func (o *Options) WriteBytes(buf []byte) (int, error) {
o.Log.Debugf("Write %d hex bytes: [%+v]", len(buf), hex.EncodeToString(buf))
return o.rc.Write(buf)
}

// WriteRegU8 writes byte to I2C-device register specified in reg.
func (o *Options) WriteRegU8(reg byte, value byte) error {
buf := []byte{reg, value}
if _, err := o.WriteBytes(buf); err != nil {
return err
}
o.Log.Debugf("Write U8 %d to reg 0x%0X", value, reg)
return nil
}

// WriteRegU16BE writes unsigned big endian word (16 bits)
// value to I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) WriteRegU16BE(reg byte, value uint16) error {
buf := []byte{reg, byte((value & 0xFF00) >> 8), byte(value & 0xFF)}
_, err := o.WriteBytes(buf)
if err != nil {
if _, err := o.WriteBytes(buf); err != nil {
return err
}
o.Log.Debugf("Write U16 %d to reg 0x%0X", value, reg)
Expand All @@ -215,19 +189,16 @@ func (o *Options) WriteRegU16BE(reg byte, value uint16) error {

// WriteRegU16LE writes unsigned little endian word (16 bits)
// value to I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) WriteRegU16LE(reg byte, value uint16) error {
w := (value*0xFF00)>>8 + value<<8
return o.WriteRegU16BE(reg, w)
}

// WriteRegS16BE writes signed big endian word (16 bits)
// value to I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) WriteRegS16BE(reg byte, value int16) error {
buf := []byte{reg, byte((uint16(value) & 0xFF00) >> 8), byte(value & 0xFF)}
_, err := o.WriteBytes(buf)
if err != nil {
if _, err := o.WriteBytes(buf); err != nil {
return err
}
o.Log.Debugf("Write S16 %d to reg 0x%0X", value, reg)
Expand All @@ -236,15 +207,40 @@ func (o *Options) WriteRegS16BE(reg byte, value int16) error {

// WriteRegS16LE writes signed little endian word (16 bits)
// value to I2C-device starting from address specified in reg.
// SMBus (System Management Bus) protocol over I2C.
func (o *Options) WriteRegS16LE(reg byte, value int16) error {
w := int16((uint16(value)*0xFF00)>>8) + value<<8
return o.WriteRegS16BE(reg, w)
}

// WriteRegU24BE writes unsigned big endian word (24 bits)
// value to I2C-device starting from address specified in reg.
func (v *Options) WriteRegU24BE(reg byte, value uint32) error {
buf := []byte{reg, byte(value >> 16 & 0xFF), byte(value >> 8 & 0xFF), byte(value & 0xFF)}
if _, err := v.WriteBytes(buf); err != nil {
return err
}
v.Log.Debugf("Write U24 %d to reg 0x%0X", value, reg)
return nil
}

// WriteRegU32BE writes unsigned big endian word (32 bits)
// value to I2C-device starting from address specified in reg.
func (v *Options) WriteRegU32BE(reg byte, value uint32) error {
buf := []byte{reg, byte(value >> 24 & 0xFF), byte(value >> 16 & 0xFF), byte(value >> 8 & 0xFF), byte(value & 0xFF)}
if _, err := v.WriteBytes(buf); err != nil {
return err
}
v.Log.Debugf("Write U32 %d to reg 0x%0X", value, reg)
return nil
}

// Close I2C-connection.
func (o *Options) Close() error {
return o.rc.Close()
}

func ioctl(fd, cmd, arg uintptr) error {
_, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, cmd, arg, 0, 0, 0)
if err != 0 {
if _, _, err := syscall.Syscall6(syscall.SYS_IOCTL, fd, cmd, arg, 0, 0, 0); err != 0 {
return err
}
return nil
Expand Down
7 changes: 3 additions & 4 deletions noncgo.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
// +build !cgo

package i2c

// Use hard-coded value for system I2C_SLAVE
// uncoment if use hard-coded value for system I2C_SLAVE
// constant, if OS not Linux or CGO disabled.
// This is not a good approach, but
// can be used as a last resort.
const (
/*const (
I2C_SLAVE = 0x0703
)
)*/

0 comments on commit bc63eef

Please sign in to comment.