i2c

package
v0.0.0-...-3466a0e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 18, 2017 License: MIT Imports: 6 Imported by: 1

README

Project Title

One Paragraph of project description goes here

Getting Started

These instructions will get you a copy of the project up and running on your local machine for development and testing purposes. See deployment for notes on how to deploy the project on a live system.

I2C Read/Write

The I2C read/write operation takes place as follows:

1.The I2C master initiates the communication by sending a START condition followed by a 7-bit slave address and the 8th bit to indicate write (0)/ read (1)).

2.The master releases the SDA and waits for an ACK from the slave device.

3.If the slave exists on the bus, it responds with an ACK.

4.The master continues in either transmit or receive mode (according to the read or write bit it sent), and the slave continues in its complementary mode (receive or transmit, respectively).

5.The master terminates the data transmission by sending a STOP condition.

The following image shows a single byte read and write on an I2C slave device.

BYTE Read:

Master Start I2C slave address+read bit NACK Stop
slave ACK Data

BYTE Write:

Master Start I2C slave address+Writebit Data Stop
slave ACK ACK
I2C Register Read/Write

The I2C register read/write operation takes place as follows:

1.The I2C master initiates the communication by sending a START condition followed by a 7-bit slave address and the 8th bit to indicate write (0)/ read (1).

2.The master releases the SDA and waits for an ACK from slave device.

3.If the slave exists on the bus, it responds with an ACK.

4.Then, the master writes the register address of the slave it wants to access.

5.Once the slave acknowledges the register address, the master sends the data byte with an ACK after each byte for write/read.

The master terminates the data transmission by sending a STOP condition.

The following image shows a single byte read and write on a register present in the I2C slave device.

IOCTL I2C_RDWR

This method allows for simultaneous read/write and sending an uninterrupted sequence of message. Not all i2c devices support this method.

Before performing i/o with this method, you should check whether the device supports this method using an ioctl I2C_FUNCS operation.

Using this method, you do not need to perform an ioctl I2C_SLAVE operation -- it is done behind the scenes using the information embedded in the messages.

IOCTL SMBUS

Because SMBus is a subset of I2C, using only SMBus commands to talk to your device yields a driver that works with both SMBus and I2C adapters. Table 8.1 lists the SMBus-compatible data transfer routines provided by the I2C core.

Function Purpose
i2c_smbus_read_byte() Reads a single byte from the device without specifying a location offset. Uses the same offset as the previously issued command.
i2c_smbus_write_byte() Sends a single byte to the device at the same memory offset as the previously issued command.
i2c_smbus_write_quick() Sends a single bit to the device (in place of the Rd/Wr bit shown in Listing 8.1).
i2c_smbus_read_byte_data() Reads a single byte from the device at a specified offset.
i2c_smbus_write_byte_data() Sends a single byte to the device at a specified offset.
i2c_smbus_read_word_data() Reads 2 bytes from the specified offset.
i2c_smbus_write_word_data() Sends 2 bytes to the specified offset.
i2c_smbus_read_block_data() Reads a block of data from the specified offset.
i2c_smbus_write_block_data() Sends a block of data (<= 32 bytes) to the specified offset.

This method of i/o is more powerful but the resulting code is more verbose. This method can be used if the device does not support the I2C_RDWR method.

Using this method, you do need to perform an ioctl I2C_SLAVE operation (or, if the device is busy, an I2C_SLAVE_FORCE operation).

SYSFS I/O

This method uses the basic file i/o system calls read() and write(). Uninterrupted sequential operations are not possible using this method. This method can be used if the device does not support the I2C_RDWR method.

Using this method, you do need to perform an ioctl I2C_SLAVE operation (or, if the device is busy, an I2C_SLAVE_FORCE operation).

I can't think of any situation when this method would be preferable to others, unless you need the chip to be treated like a file.

Prerequisites

What things you need to install the software and how to install them

Give examples
Installing

A step by step series of examples that tell you have to get a development env running

Say what the step will be

Give the example

And repeat

until finished

End with an example of getting some data out of the system or using it for a little demo

Running the tests

Explain how to run the automated tests for this system

Break down into end to end tests

Explain what these tests test and why

Give an example
And coding style tests

Explain what these tests test and why

go.exe test -timeout 30s -tags -run ^Test_getEndian$

Give an example

Deployment

Add additional notes about how to deploy this on a live system

Built With

  • Dropwizard - The web framework used
  • Maven - Dependency Management
  • ROME - Used to generate RSS Feeds

Contributing

Please read CONTRIBUTING.md for details on our code of conduct, and the process for submitting pull requests to us.

Versioning

We use SemVer for versioning. For the versions available, see the tags on this repository.

Authors

See also the list of contributors who participated in this project.

License

This project is licensed under the MIT License - see the LICENSE.md file for details

Acknowledgments

  • Hat tip to anyone who's code was used

  • Inspiration

  • etc

  • c sampleFull IOCTL Example

from : http://stackoverflow.com/questions/9974592/i2c-slave-ioctl-purpose I haven't tested this example, but it shows the conceptual flow of writing to an i2c device.-- automatically detecting whether to use the ioctl I2C_RDWR or smbus technique.

#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>

#include <errno.h>
#include <string.h>

#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>

#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <sys/ioctl.h>

#define I2C_ADAPTER "/dev/i2c-0"
#define I2C_DEVICE  0x00

int i2c_ioctl_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data)
{
    int i, j = 0;
    int ret;
    uint8_t *buf;

    buf = malloc(1 + 2 * (sizeof(data) / sizeof(data[0])));
    if (buf == NULL) {
        return -ENOMEM;
    }

    buf[j ++] = regaddr;
    for (i = 0; i < (sizeof(data) / sizeof(data[0])); i ++) {
        buf[j ++] = (data[i] & 0xff00) >> 8;
        buf[j ++] = data[i] & 0xff;
    }

    struct i2c_msg messages[] = {
        {
            .addr = dev,
            .buf = buf,
            .len = sizeof(buf) / sizeof(buf[0]),
        },
    };

    struct i2c_rdwr_ioctl_data payload = {
        .msgs = messages,
        .nmsgs = sizeof(messages) / sizeof(messages[0]),
    };

    ret = ioctl(fd, I2C_RDWR, &payload);
    if (ret < 0) {
        ret = -errno;
    }

    free (buf);
    return ret;
}

int i2c_ioctl_smbus_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data)
{
    int i, j = 0;
    int ret;
    uint8_t *buf;

    buf = malloc(2 * (sizeof(data) / sizeof(data[0])));
    if (buf == NULL) {
        return -ENOMEM;
    }

    for (i = 0; i < (sizeof(data) / sizeof(data[0])); i ++) {
        buf[j ++] = (data[i] & 0xff00) >> 8;
        buf[j ++] = data[i] & 0xff;
    }

    struct i2c_smbus_ioctl_data payload = {
        .read_write = I2C_SMBUS_WRITE,
        .size = I2C_SMBUS_WORD_DATA,
        .command = regaddr,
        .data = (void *) buf,
    };

    ret = ioctl (fd, I2C_SLAVE_FORCE, dev);
    if (ret < 0)
    {
        ret = -errno;
        goto exit;
    }

    ret = ioctl (fd, I2C_SMBUS, &payload);
    if (ret < 0)
    {
        ret = -errno;
        goto exit;
    }

exit:
    free(buf);
    return ret;
}

int i2c_write (int fd, uint8_t dev, uint8_t regaddr, uint16_t *data)
{
    uint64_t funcs;

    if (ioctl(fd, I2C_FUNCS, &funcs) < 0) {
        return -errno;
    }

    if (funcs & I2C_FUNC_I2C) {
        return i2c_ioctl_write (fd, dev, regaddr, data);
    } else if (funcs & I2C_FUNC_SMBUS_WORD_DATA) {
        return i2c_ioctl_smbus_write (fd, dev, regaddr, data);
    } else {
        return -ENOSYS;
    }
}

int parse_args (uint8_t *regaddr, uint16_t *data, char *argv[])
{
    char *endptr;
    int i;

    *regaddr = (uint8_t) strtol(argv[1], &endptr, 0);
    if (errno || endptr == argv[1]) {
        return -1;
    }

    for (i = 0; i < sizeof(data) / sizeof(data[0]); i ++) {
        data[i] = (uint16_t) strtol(argv[i + 2], &endptr, 0);
        if (errno || endptr == argv[i + 2]) {
            return -1;
        }
    }

    return 0;
}

void usage (int argc, char *argv[])
{
    fprintf(stderr, "Usage: %s regaddr data [data]*\n", argv[0]);
    fprintf(stderr, "  regaddr   The 8-bit register address to write to.\n");
    fprintf(stderr, "  data      The 16-bit data to be written.\n");
    exit(-1);
}

int main (int argc, char *argv[])
{
    uint8_t regaddr;
    uint16_t *data;
    int fd;
    int ret = 0;

    if (argc < 3) {
        usage(argc, argv);
    }

    data = malloc((argc - 2) * sizeof(uint16_t));
    if (data == NULL) {
        fprintf (stderr, "%s.\n", strerror(ENOMEM));
        return -ENOMEM;
    }

    if (parse_args(&regaddr, data, argv) != 0) {
        free(data);
        usage(argc, argv);
    }

    fd = open(I2C_ADAPTER, O_RDWR | O_NONBLOCK);
    ret = i2c_write(fd, I2C_DEVICE, regaddr, data);
    close(fd);

    if (ret) {
        fprintf (stderr, "%s.\n", strerror(-ret));
    }

    free(data);

    return ret;
}

Documentation

Index

Constants

View Source
const (
	I2cSMBus      = 0x720
	I2cSlaveForce = 0x706
	I2cSlave      = 0x703

	I2cSMBusRead  = 0x1
	I2cSMBusWrite = 0x0

	I2cSMBusQuick        = 0x0
	I2cSMBusByte         = 0x1
	I2cSMBusByteData     = 0x2
	I2cSMBusWordData     = 0x3
	I2cSMBusProcCall     = 0x4
	I2cSMBusBlockData    = 0x5
	I2cSMBusI2cBlockData = 0x8
)
View Source
const (
	I2cFuncs = 0x705
	I2cRDWR  = 0x707
)
View Source
const (
	I2cSmBusBlockMax    = 0x20
	I2cSmBusI2cBlockMax = I2cSmBusBlockMax
)
View Source
const (
	I2cFuncI2c = 0x1
)
View Source
const (
	Sizeofi2c_smbus_ioctl_data = 0x10
)

Variables

This section is empty.

Functions

func TenBit

func TenBit(addr int) int

TenBit marks an I2C address as a 10-bit address.

Types

type Device

type Device struct {
	sync.Mutex
	// contains filtered or unexported fields
}

Device represents an active connection to an I2C device.

func Open

func Open(device string) (d *Device, err error)

Open opens a connection to an I2C slave device. All devices must be closed once they are no longer in use. TODO(jbd): Support I2C_RETRIES and I2C_TIMEOUT at the driver and implementation level.

func (*Device) Close

func (d *Device) Close() (err error)

func (*Device) GetName

func (d *Device) GetName() string

func (*Device) SetAddr

func (d *Device) SetAddr(addr int) (err error)

SetAddr set the I2C slave address for all subsequent I2C device transfers For devices that use 10-bit I2C addresses, addr can be marked as a 10-bit address with TenBit. set a 10-bit address example: err = d.SetAddr( i2c.TenBit(0x78))

func (*Device) SmbusProcessCall

func (d *Device) SmbusProcessCall(command uint8, value uint16) (data uint16, err error)

func (*Device) SmbusReadBlockData

func (d *Device) SmbusReadBlockData(command uint8) (block []byte, err error)

SmbusReadBlockData Reads a block of data from the specified offset.

func (*Device) SmbusReadByte

func (d *Device) SmbusReadByte() (data uint8, err error)

SmbusReadByte Reads a single byte from the device without specifying a location offset. Uses the same offset as the previously issued command.

func (*Device) SmbusReadByteData

func (d *Device) SmbusReadByteData(command uint8) (data uint8, err error)

SmbusReadByteData Reads a single byte from the device at a specified offset.

func (*Device) SmbusReadWordData

func (d *Device) SmbusReadWordData(command uint8) (data uint16, err error)

SmbusReadWordData Reads 2 bytes from the specified offset.

func (*Device) SmbusWriteBlockData

func (d *Device) SmbusWriteBlockData(command uint8, length uint8, value []byte) (err error)

SmbusWriteBlockData Sends a block of data (<= 32 bytes) to the specified offset.

func (*Device) SmbusWriteByte

func (d *Device) SmbusWriteByte(value uint8) error

SmbusWriteByte Sends a single byte to the device at the same memory offset as the previously issued command.

func (*Device) SmbusWriteByteData

func (d *Device) SmbusWriteByteData(command uint8, value uint8) (err error)

SmbusWriteByteData Sends a single byte to the device at a specified offset.

func (*Device) SmbusWriteI2cBlockData

func (d *Device) SmbusWriteI2cBlockData(command uint8, length uint8, value []byte) (err error)

func (*Device) SmbusWriteQuick

func (d *Device) SmbusWriteQuick(value uint8) error

SmbusWriteQuick Sends a single bit to the device (in place of the Rd/Wr bit shown in Listing 8.1).

func (*Device) SmbusWriteWordData

func (d *Device) SmbusWriteWordData(command uint8, value uint16) (err error)

SmbusWriteWordData Sends 2 bytes to the specified offset.

func (*Device) SysfsRead

func (d *Device) SysfsRead(buf []byte) error

SysfsRead reads len(buf) bytes from the device.

func (*Device) SysfsReadReg

func (d *Device) SysfsReadReg(reg byte, buf []byte) error

SysfsReadReg is similar to Read but it reads from a register.

func (*Device) SysfsWrite

func (d *Device) SysfsWrite(buf []byte) (err error)

SysfsWrite writes the buffer to the device. If it is required to write to a specific register, the register should be passed as the first byte in the given buffer.

func (*Device) SysfsWriteReg

func (d *Device) SysfsWriteReg(reg byte, buf []byte) (err error)

SysfsWriteReg is similar to Write but writes to a register.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL