Staton.us

NSLU2 I²C Interface

This voids your warranty. Good soldering skills are required.

If you stumbled across this page and don't know what a NSLU2 is,

you can read about it here.

Connector

The I²C interface is addressable and supports multiple devices on the same interface provided that each device has a unique address.
I chose to add a connector on top of the X1205 Real Time Clock I²C device.

connector image

The connector is a 1.27mm surface mount part (Samtec FTS-105-01-F-DV-P)
It is glued to the top of the X1205, then wires were soldered from X1205 pins 4,5,6, and 8 to the connector pins immediately above the IC pins.
Note that the connector has 10 pins and the IC has 8. Shift the two extra connector pins away from the edge of the PCB.

C code access routines

We need a read, write, open and close.
Here is my test code. I used this to write and then read 0xAA at address 0x10 in a 24LC256 (device address 0x50).

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>

int main(){

int file;
int addr = 0x50;
unsigned short reg = 0x10;
char buf[10];
int n;



if ((file = open("/dev/i2c0", O_RDWR)) < 0) {
	printf("open error!\n");
	exit(1);
}

if (ioctl(file,I2C_SLAVE_FORCE,addr) < 0) {
	printf("address error!\n");
	exit(1);
}

buf[0] = 0x00;
buf[1] = reg;
buf[2] = 0xaa;


printf("write: ");
n=write(file,buf,3);
if (n != 3) {
	printf("write error! %d\n",n);
	exit(1);
}

printf("read: ");
n=write(file,buf,2); /* set address for random read */
if (n != 2) {
	printf("addr write error! %d\n",n);
	exit(1);
}
n=read(file,buf,1);
if (n != 1) {
	printf("read error! %d\n",n);
	exit(1);
} else {
	printf("0x%x\n",buf[0]);
}



close(file);


}

Python I²C Library

I prefer Python for developing new systems.

Use ipkg to set up a development environment with Python.

ipkg install openslug-native


Make sure you have python-devel.

You also need the gcc tools to compile the Python extension.

SWIG Python wrapper

You don't need to run SWIG on the SLUG. Run this interface file through SWIG to generate the wrapper source (C) and the interface shadow code (Python).

i2c.i - the swig interface file

%module i2c

int openi2c(int dev_addr);
int writei2c(int addr, int data);
int readi2c(int addr);
int closei2c();

i2clib.c - the access routines (for 24LC256)

#include <stdio.h>
#include <sys/types.h>
#include <fcntl.h>
#include <linux/i2c-dev.h>

int file;

int openi2c(int dev_addr){

  if ((file = open("/dev/i2c0", O_RDWR)) < 0) {
  	printf("open error!\n");
	return(-1);
  }

  if (ioctl(file,I2C_SLAVE_FORCE,dev_addr) < 0) {
	printf("address error!\n");
	return(-2);
  }
  return(file);

}

int writei2c(int addr, char data){

  int n;
  char databuf[8];
  databuf[0]=(addr>>8 & 0xff);
  databuf[1]=(addr&0xff);
  databuf[2]=data;

  n=write(file,databuf,3);
  if (n != 3) {
	printf("write error! %d\n",n);
	return(-1);
  }
  return(data);
}

int readi2c(int addr){

  int n;
  char databuf[8];
  databuf[0]=(addr>>8 & 0xff);
  databuf[1]=(addr&0xff);

  n=write(file,databuf,2); /* set address for random read */
  if (n != 2) {
	printf("addr write error! %d\n",n);
	return(-1);
  }

  n=read(file,databuf,1);
  if (n != 1) {
	printf("read error! %d\n",n);
	return(-2);
  } else {
	return(databuf[0]);
  }
}


int closei2c(){

  close(file);
}

compile and link:

gcc -c i2c_wrap.c i2clib.c -I/usr/include/python2.4 -fpic
gcc -shared i2c_wrap.o i2clib.o -L/usr/lib/python2.4 -Xlinker -export-dynamic -o _i2c.so

I²C Programmable Peripheral

Some Microchip parts have I²C support. It is reasonably easy to modify my Programmable Peripheral to provide PWM servo, A/D and parallel I/O for a NSLU2.

I constructed a simple test case using a PIC16F88 as an I²C slave.

 

This turned out to be harder than I expected.
An oscilloscope really helps.

The slave test code is a modified version of Microchip's AN734.
My modifications make it compatible with the i2clib master interface on this page.
This slave device uses a single byte address to specifiy a PIC register to read or write.
Addresses from 0x30 to 0x7F are unused and can be written and read using the i2clib interface for PIC (or 24L01).

This part can be turned into a Programmable Peripheral by adding I/O functions.
The basic idea is to define I²C registers that invoke peripheral functions.
I've fabricated a PCB with the PIC16F88 configured as an I²C to parallel slave port interface.
This will allow using an unmodified Programmable Peripheral.

Building blocks are great.

 

i2c I/O
16F88 wired to NSLU2

 

i2c I/O
16F88 I²C Interface

 

Programmable Peripheral
I²C Interface with Programmable Peripheral


| © 2005, 2008 Ken Staton