Skip Headers
Oracle® Java ME Embedded Device Access API Guide
Release 3.3
E35134-02
  Go To Table Of Contents
Contents
Go To Index
Index

Previous
Previous
 
Next
Next
 

8 Inter-Integrated Circuit Bus

This chapter describes the interfaces and classes for Inter-Integrated Circuit Bus control. I²C (often pronounced "i-squared C") is a multi-master serial single-ended computer bus that is used to attach low-speed peripherals to an embedded system or other electronic device.

The functionalities supported by this API are those of an I²C master. In order to communicate with a specific slave device, an application should first open and obtain an I2CDevice instance for the I²C slave device the application wants to exchange data with, using its numerical ID, name, type (interface) or properties. This is an example of using its ID:

 I2CDevice slave = (I2CDevice) PeripheralManager.open(3);
 

This is an example of using its name and interface:

 I2CDevice slave = (I2CDevice) PeripheralManager.open("ADC1",
     I2CDevice.class, null);
 

Once the peripheral opened, the application can exchange data with the I²C slave device using methods of the I2CDevice interface such as the write() method.

 slave.write(sndBuf, 0, 1);
 

When the data exchange is over, the application should call the Peripheral.close() method to release I²C slave device.

 slave.close();
 

Example 8-1 and Example 8-2 demonstrate two ways of using the I²C API to communicate with an I²C slave device.

Example 8-1 Using the I2C APIs to Interact with LEDs

import com.oracle.deviceaccess.PeripheralException;
import com.oracle.deviceaccess.PeripheralManager;
import com.oracle.deviceaccess.i2cbus.I2CDevice;
import java.io.IOException;
 
public class I2CExample1 {
 
    public static final String LED_SLAVE_NAME = "LED_CONTROLLER";
    public static final byte[] LED_STOP_COMMAND = null;
    public static final byte[] LED_OFF_COMMAND = null;
    public static final byte[] LED_ON_COMMAND = null;
    public static int LED_LOOP_COUNT = 10;
    public static long LED_BLINK_TIME = 1500;
    I2CDevice slave = null;
 
    public I2CExample1() {
        try {
            slave = (I2CDevice) PeripheralManager.open(
                LED_SLAVE_NAME, I2CDevice.class, (String[]) null);
            // Clear all status of the 'LED' slave device
            slave.write(LED_STOP_COMMAND, 0, LED_STOP_COMMAND.length);
            slave.write(LED_OFF_COMMAND, 0, LED_OFF_COMMAND.length);
 
            for (int i = 0; i < LED_LOOP_COUNT; i++) {
                // turning 'LED' on and keeping it on for 1500ms
                slave.write(LED_ON_COMMAND, 0, LED_ON_COMMAND.length);
                try {
                    Thread.sleep(LED_BLINK_TIME);
                } catch (InterruptedException ex) {
                }
 
                // turning 'LED' off keeping it off for 1500ms
                slave.write(LED_OFF_COMMAND, 0, LED_OFF_COMMAND.length);
                try {
                    Thread.sleep(LED_BLINK_TIME);
                } catch (InterruptedException ex) {
                }
            }
        } catch (IOException ex) {
            // Handle exception
        } catch (PeripheralException ex) {
            // Handle exception
        } finally {
            if (slave != null) {
                try {
                    slave.close();
                } catch (IOException ex) {
                }
            }
        }
    }
}

Example 8-2 Writing and Reading Data Using the I2C APIs

import com.oracle.deviceaccess.PeripheralManager;
import com.oracle.deviceaccess.PeripheralNotAvailableException;
import com.oracle.deviceaccess.PeripheralNotFoundException;
import com.oracle.deviceaccess.PeripheralTypeNotSupportedException;
import com.oracle.deviceaccess.i2cbus.I2CDevice;
import java.io.IOException;
 
public class I2CExample2 {
 
    I2CDevice slave = null;
 
    public I2CExample2() {
        try {
            slave = (I2CDevice) PeripheralManager.open("EEPROM",
                     I2CDevice.class, (String[]) null);

            byte[] addr = new byte[4];
            byte[] data = new byte[4];
            
            try {
                slave.begin();
                slave.write(addr, 0, 2); // Writes the address
                int count = slave.read(data, 0, 1);
                // Read the data at that EEPROM address
            } finally {
                slave.end();
            }
            
        } catch (PeripheralNotAvailableException ex) {
            ex.printStackTrace();
        } catch (PeripheralNotFoundException ex) {
            ex.printStackTrace();
        } catch (PeripheralTypeNotSupportedException ex) {
            ex.printStackTrace();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (slave != null) {
                try {
                    slave.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
     }
 
}

More information about the I²C-bus specification can be found at http://www.nxp.com/documents/user_manual/UM10204.pdf

I²C slave devices are opened by invoking one of the com.oracle.deviceaccess.PeripheralManager.open() methods. The com.oracle.deviceaccess.i2c permission allows access to be granted to I²C slave devices as a whole. This permission must be requested in the JAD file under MIDlet-Permissions or MIDlet-Permissions-Opt, and the application must be digitally signed by a trusted authority to gain access to the APIs. Alternatively, the permission may be allowed for all applications in the untrusted domain of the security policy file (policy.txt).

The I2CDevice Interface

The I2CDevice interface provides methods for sending and receiving data to and from an I²C slave device. Each I²C slave device is identified by both a numerical ID and a name. An I2CDevice instance can be acquired by a call to one of the PeripheralManager.open() methods.On an I²C bus, data is transferred between the I²C master device and an I²C slave device through single or combined messages. With single messages, the approach is simple: the I²C master can read data from an I²C slave using one of the read() methods and can write data to an I²C slave using one of the write() methods. With combined messages, the I²C master issues at least two reads or writes to one or more slaves. Issuing multiple reads and writes to several slaves is not supported. However, if the master is communicating with a single slave, it can explicitly start a combined message by calling the begin() method, issuing several read or write operations using the read() and write() methods, then end the combined message by calling the end() method. An application can also use the convenience methods read(subaddress, subaddressSize,...) and write(subaddress, subaddressSize,...), which read and write from slave device subaddresses or register addresses.

The following example illustrates the use of begin() and end() to implement the read(subaddress, subaddressSize,...) method:

public int read(int subaddress, int subaddressSize, byte[] dstBuf, int dstOff,
     int dstLen) throws IOException, PeripheralNotAvailableException
 {
     if (subaddress < 0 || subaddressSize < 1 || subaddressSize > 4)
         throw IllegalArgumentException();

     byte[] subaddr = new byte[] { (byte) ((subaddress >> 24) & 0xFF),
                                   (byte) ((subaddress >> 16) & 0xFF),
                                   (byte) ((subaddress >> 8) & 0xFF),
                                   (byte) ((subaddress >> 0) & 0xFF)
     };

     try {
         begin();
         write(subaddr, subaddr.length - subaddressSize,
               subaddressSize); // Writes the subaddress
         return read(dstBuf, dstOff, dstLen); // Read the data at that subaddress
     } finally {
         end();
     }
}

When exchanging data, the most significant bytes of data are stored at the lower index (first) in the sending and receiving byte buffers.

When the data exchange is over, an application should call the I2CDevice.close() method to release the I²C slave device. Any further attempt to write to or read from an I²C slave device which has been closed will throw a PeripheralNotAvailableException. Note that the current API does not allow for reading and writing subsequently to and from different buffers without sending a repeated start between subsequent reads or writes.

The I2CDevice interface consists of the following methods:

The I2CDeviceConfig Class

The I2CDeviceConfig class encapsulates the configuration parameters of an I²C slave device. An instance of I2CDeviceConfig can be passed to the PeripheralManager.open(PeripheralConfig) method to open the designated I²C slave device with the specified configuration.

The I2CDeviceConfig class consists of one constructor and five methods.