Experiments with i2c on the (OpenWrt Kamikaze and Debian) Linksys NSLU2 - the Slug
  Working drivers for PCF8574 (port expander) and PCF9591 (A/D D/A)
  for the LM75 thermometer all is OK on Debian Slug but for OpenWrt 
  slug I need a "work around" see below 
For OpenWrt an ipackage lets you add
 - i2cdetect
- i2cdump
- i2cget
- i2cset
use "apt-get install lm-sensors" for Debian
My i2c test board was connected via a Philips designed FET level shifter 
(as for the Sweex menu item 6) and I ran "i2cdetect 0" to find my chip addresses - 
 0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
  00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
  10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  20: -- -- -- -- -- -- -- 27 -- -- -- -- -- -- -- -- 
  30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  40: -- -- -- -- -- -- -- -- 48 -- -- -- 4c -- -- -- 
  50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
  60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- UU 
70: -- -- -- -- -- -- -- -- 
So my chips are at 
  PCF8574 port expander - - -  0x27 = dec39
  LM75 thermometer - - - - - - - 0x48 = dec72
  PCF8591 A/D D/A - - - - - - - 0x4c= dec76
I suppose UU is the RTC - real time clock on the Slug board.
I tried to compile my c drivers that worked in the Sweex but they failed
I did some Googling many thanks to this link and cutting and pasting from i2cget and i2cset and the following work fine
    This is pure Lesson 1 C-code (copy and pray) - please email me if you can up the quality! 
/*   usage :-  type with spaces but without the < > */  int i2c;  int rc; int main(int argc, char *argv[])   /* address is the first number after the program name */ i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */ write(i2c,data,1) ; /* send the byte */  i2c = close(i2c); /* Sunspot 080607 */  | 
  
/*   1) set the i2c address of the PCF8574 #include <stdio.h>  int i2c; int main(int argc, char ** argv)   /* address is the first number after the program name */  i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */  data[0] = 255;  read(i2c,data,1); /* now data(0) contains the byte of data on the 8 port lines*/ byte = data[0];  printf("BYTE = %d \n", byte);   i2c = close(i2c); 
 /* Sunspot 080607 */  | 
  
/*  #include <stdio.h>  int i2c;  int main(int argc, char** argv) { printf("Error. usage: %s i2c_chip_address D/A_Vout(0-255)\n", argv[0]); } address = atoi(argv[1]); /* address is the first number after the program name */ V_out = atoi(argv[2]); /* A/D input line 0-3 */  i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */  AD_line = 0 + 64;   /* enable the D/A output pin 0*/  AD_line = 1 + 64;   /* enable the D/A output pin 0*/  AD_line = 2 + 64;   /* enable the D/A output pin 0*/  AD_line = 3 + 64;   /* enable the D/A output pin 0*/ printf("A/D line 0 = %d \n", AD_line_0, " ");  /*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/  i2c = close(i2c);  | 
  
/*  #include <stdio.h>  int i2c;  int rc; int main(int argc, char** argv)  address = atoi(argv[1]); /* decimal address is the first number after the program name */  i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */  channel = channel + 64;   /* enable the D/A output */ 
 printf("%d", AD_input); 
 /*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/  i2c = close(i2c);  | 
  
/* */ #include <stdio.h>  int i2c;  /* address is the first number after the program name */  i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ read(i2c,data,2);  byte1 = data[0];  temperature = byte1*256+byte2; printf("%d \n", temperature*5); //cast and divide by 2 (next 2 lines) compiles but gave run error:-  i2c = close(i2c); ----------------------------------------------------------------------- I found a way to work round this problem and divide by 10 in a script- Inside my ash script that builds a web page reporting the temperature I use AWK like this -  result=`echo $realtemp | awk "$AWKSCRIPT"` echo "<BR><HR> result of AWK print = " - this does the printing and 51, for example, becomes 25.5 as required - or I can get a new ash string result = 25.5 (for example)   | 
  
For Debian Slug the print statements compile and run OK - no need for the "work-around" above This code just gives the temperature as a string of characters (eg 23.5) with no return character for i2c decimal address 72 use ./LM75-Deb-slug 72 /*  */ #include <stdio.h>  int i2c;  /* address is the first number after the program name */  i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */ read(i2c,data,2);  byte1 = data[0];  temperature = byte1*256+byte2; /* the following 2 lines compile and run for Debian Slug  i2c = close(i2c);  | 
  
Use a Blassic basic program with i2cset and i2cget  SE95_i2ctools_read_once.bas #!/usr/sbin/blassic address$ = PROGRAMARG$(1) 'write a 0 to the 0 register SHELL "i2cget -y 0 "+address$+" 0x00 w > /var/www/ramdisk/lm75_1.txt" 'get the two hex bytes from the stored text string 'get the decimal value of the hex numbers sign  = 1 temp_all = (HI_dec + LO_dec/256) SYSTEM  |