Initial fork + minor fixes for BMP085 (mBar output) + shell scripts for ADS1115 and...
authorRoman Bazalevskiy <rvb@rvb-work.glas.net>
Wed, 12 Apr 2017 17:05:42 +0000 (20:05 +0300)
committerRoman Bazalevskiy <rvb@rvb-work.glas.net>
Wed, 12 Apr 2017 17:05:42 +0000 (20:05 +0300)
29 files changed:
Makefile [new file with mode: 0644]
ad5602_test.c [new file with mode: 0644]
ads1115 [new file with mode: 0644]
am2321.c [new file with mode: 0644]
bh1750.c [new file with mode: 0644]
bmp085.c [new file with mode: 0644]
ds1621.c [new file with mode: 0644]
etraxi2c.h [new file with mode: 0644]
gethwclock [new file with mode: 0644]
i2c_errno.h [new file with mode: 0644]
i2cget_bmp180.example [new file with mode: 0644]
ina219.c [new file with mode: 0644]
lcdd.c [new file with mode: 0644]
lm75.c [new file with mode: 0644]
mcp_rw.c [new file with mode: 0644]
pcf8574_1.c [new file with mode: 0644]
pcf8574_2.c [new file with mode: 0644]
pcf8574_3.c [new file with mode: 0644]
pcf8574_4.c [new file with mode: 0644]
pcf8591_1.c [new file with mode: 0644]
pcf8591_2.c [new file with mode: 0644]
pcf8591_3.c [new file with mode: 0644]
pcf8591_4.c [new file with mode: 0644]
pcf8591d.c [new file with mode: 0644]
sethwclock [new file with mode: 0644]
sht21.c [new file with mode: 0644]
smbus.c [new file with mode: 0644]
smbus.h [new file with mode: 0644]
syncfromhwclock [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..e27fcce
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,33 @@
+
+STAGING_DIR=/var/www/builder/data/trunk/build_ng/openwrt/staging_dir
+export STAGING_DIR
+CFLAGS=-I.
+#
+# Atheros
+CC= ~/trunk/build_ng/openwrt/staging_dir/toolchain-mips_r2_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-uclibc-gcc
+#
+# Broadcom
+#CC= ~/trunk/build_ng/openwrt/staging_dir/toolchain-mips_gcc-4.6-linaro_uClibc-0.9.33.2/bin/mips-openwrt-linux-uclibc-gcc
+
+
+
+ina219:
+       $(CC) -o ina219 ina219.c
+
+bmp085:
+       $(CC) -o bmp085 bmp085.c smbus.c
+
+lm75:
+       $(CC) -o lm75 lm75.c
+
+ds1621:
+       $(CC) -o ds1621 ds1621.c
+
+bh1750:
+       $(CC) -o bh1750 bh1750.c smbus.c
+
+lcdd:
+       $(CC) -o lcdd lcdd.c
+
+mcp_rw:
+       $(CC) -o mcp mcp_rw.c smbus.c
diff --git a/ad5602_test.c b/ad5602_test.c
new file mode 100644 (file)
index 0000000..4b67a3d
--- /dev/null
@@ -0,0 +1,60 @@
+/* 
+    AD5602_test1.c
+    ---------------------
+    set the output voltage from the D/A
+    -----------------------------------
+      1) send the i2c address
+      2) send HI_byte
+      3) send LO_byte
+      
+       usage :-  type with spaces but without the < >
+       <AD5602_test1>  <address as decimal> <HI_byte> <LO_byte>
+*/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/i2c.h>
+
+int main(int argc, char** argv)
+{
+  int i2c; 
+  int HI_byte;   /* last 4 bits are output byte HI bits */
+  int LO_byte;   /* first 4 bits are output byte LO bits */
+  int buf[1];    /* use to feed the i2c driver */
+  int address;   /* i2c bus address */
+
+ if (argc != 4)   /* report error if we are not getting just 3 inputs after the program name */
+ {
+  printf("Error. usage (decimal): %s AD5602_test1 address HI_byte LO_byte\n", argv[0]);           
+ }
+
+  address = atoi(argv[1]); /* address is the first number after the program name */
+  // address bits are  0 0 0 1   1 1 0 R/W as per manual
+  // the 1 0  before R/W is for the address pin (pin 1) open-circuit
+  // the R/W is 0 for write. Linux see the chip address as 0000 1110 (0E) - shifts a bit to the left - odd!
+  HI_byte = atoi(argv[2]); /* HI_byte is 0 0 0 0 D7 D6 D5 D4   */
+  LO_byte = atoi(argv[3]); /* LO_byte is D3 D2 D1 D0 X X X X   (X = anything) */
+
+  i2c = open("/dev/i2c/0",O_RDWR); /* open the i2c-bus number 0 */
+
+  ioctl(i2c,I2C_SLAVE,address); /* set the i2c-bus address of the chip we will talk to */
+
+  buf[0] = HI_byte;         /* HI_byte */
+  buf[1] = LO_byte;         /* LO_byte */
+
+
+  write(i2c,buf,2); /* we send 2 bytes <HI_byte> <LO_byte> */
+
+  printf("%d\n", buf[0]); /* just to prove it ran!*/
+  printf("%d\n", buf[1]);
+
+  i2c = close(i2c);
+}
+
+//  AD5602_test1 14 0 0  gives 0 volts
+//  AD5602_test1 14 8 0  gives 2.5 volts     8 = 08 00001000    0 = 00 00000000
+//  AD5602_test1 14 15 240  gives 5 volts   15 = 0F 00001111  240 = F0 11110000
+
diff --git a/ads1115 b/ads1115
new file mode 100644 (file)
index 0000000..2f1e824
--- /dev/null
+++ b/ads1115
@@ -0,0 +1,33 @@
+#!/bin/sh
+
+I2CBUS=0
+I2CADDR=0x48
+
+if [ "$1" == "" ]
+then
+  pin=0
+else
+  pin=$1
+fi
+
+case "$pin" in
+  "0") CFG="0xc583" ;;
+  "1") CFG="0xc593" ;;
+  "2") CFG="0xc5a3" ;;
+  "3") CFG="0xc5b3" ;;
+  *) echo "Bad pin number $pin, must be 0..3" ; exit 1 ;;
+esac
+
+i2cset -y 0 0x48 1 $CFG w
+RES=`i2cget -y 0 0x48 1 w`
+until [ "$RES" = "$CFG" ] ; do
+  RES=`i2cget -y 0 0x48 1 w`
+done
+X=`i2cget -y 0 0x48 0 w`
+
+XX="0x0`echo $X | cut -c 5-6``echo $X | cut -c 3`"
+VIND=$(( ( $XX + 32768 / 40960 ) * 20480 / 32768 ))
+VIN=$(( $VIND / 10 ))
+VINF=$(( $VIND - $VIN * 10 ))
+
+printf "VIN$pin (mv) %d.%01d\n" $VIN $VINF
diff --git a/am2321.c b/am2321.c
new file mode 100644 (file)
index 0000000..abe84bc
--- /dev/null
+++ b/am2321.c
@@ -0,0 +1,303 @@
+/*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+*
+* Project Home - https://github.com/takagi/am2321
+*
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>              /* for O_RDWR */
+#include <string.h>             /* for memcpy */
+#include <linux/i2c-dev.h>      /* for I2C_SLAVE */
+
+#include <unistd.h>             /* add by paulerr*/
+#include <sys/time.h>           /* add by paulerr*/
+
+
+/* I2C character device */
+#define I2C_DEVICE "/dev/i2c-0"
+
+/* I2C address of AM2321 sensor in 7 bits
+ * - the first 7 bits should be passed to ioctl system call
+ *   because the least 1 bit of the address represents read/write
+ *   and the i2c driver takes care of it
+ */
+#define AM2321_ADDR (0xB8 >> 1)
+
+
+/*
+ *  udelay function
+ */
+
+long timeval_to_usec( struct timeval tm ) {
+  return tm.tv_sec * 1000000 + tm.tv_usec;
+}
+
+void udelay( long us ) {
+  struct timeval current;
+  struct timeval start;
+  
+  gettimeofday( &start, NULL );
+  do {
+    gettimeofday( &current, NULL );
+  } while( timeval_to_usec( current ) - timeval_to_usec( start ) < us );
+}
+
+
+/*
+ *  CRC16
+ */
+
+unsigned short crc16( unsigned char *ptr, unsigned char len ) {
+  unsigned short crc = 0xFFFF;
+  unsigned char i;
+
+  while( len-- )
+  {
+    crc ^= *ptr++;
+    for( i = 0; i < 8; i++ ) {
+      if( crc & 0x01 ) {
+       crc >>= 1;
+       crc ^= 0xA001;
+      } else {
+       crc >>= 1;
+      }
+    }
+  }
+
+  return crc;
+}
+
+unsigned char crc16_low( unsigned short crc ) {
+  return crc & 0xFF;
+}
+
+unsigned char crc16_high( unsigned short crc ) {
+  return crc >> 8;
+}
+
+
+/*
+ *  st_am2321 Structure
+ */
+
+typedef struct {
+  unsigned char data[8];
+} st_am2321;
+
+void __check_crc16( st_am2321 measured ) {
+  unsigned short crc_m, crc_s;
+
+  crc_m = crc16( measured.data, 6 );
+  crc_s = (measured.data[7] << 8) + measured.data[6];
+  if ( crc_m != crc_s ) {
+    fprintf( stderr, "am2321: CRC16 does not match\n" );
+    exit( 1 );
+  }
+
+  return;
+}
+
+st_am2321 __st_am2321( unsigned char* data ) {
+  st_am2321 result;
+  memcpy( result.data, data, 8 );
+  __check_crc16( result );
+  return result;
+}
+
+void am2321_dump( st_am2321 measured ) {
+  printf( "[ 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x 0x%02x ]\n",
+          measured.data[0], measured.data[1],
+          measured.data[2], measured.data[3],
+          measured.data[4], measured.data[5],
+          measured.data[6], measured.data[7] );
+  return;
+}
+
+short __am2321_temperature( st_am2321 measured ) {
+  return (measured.data[4] << 8) + measured.data[5];
+}
+
+short am2321_temperature_integral( st_am2321 measured ) {
+  return __am2321_temperature( measured ) / 10;
+}
+
+short am2321_temperature_fraction( st_am2321 measured ) {
+  return __am2321_temperature( measured ) % 10;
+}
+
+short __am2321_humidity( st_am2321 measured ) {
+  return (measured.data[2] << 8) + measured.data[3];
+}
+
+short am2321_humidity_integral( st_am2321 measured ) {
+  return __am2321_humidity( measured ) / 10;
+}
+
+short am2321_humidity_fraction( st_am2321 measured ) {
+  return __am2321_humidity( measured ) % 10;
+}
+
+
+/*
+ *  Measurement function
+ */
+
+st_am2321 am2321() {
+  int fd;
+  int ret;
+  int retry_cnt;
+  unsigned char data[8];
+
+  /* open I2C device */
+  fd = open( I2C_DEVICE, O_RDWR );
+  if ( fd < 0 ) {
+    perror( "am2321(1)" );
+    exit( 1 );
+  }
+
+  /* set address of I2C device in 7 bits */
+  ret = ioctl( fd, I2C_SLAVE, AM2321_ADDR );
+  if ( ret < 0 ) {
+    perror( "am2321(2)" );
+    exit( 2 );
+  }
+
+ retry_cnt = 0;
+ retry:
+
+  /* wake I2C device up */
+  write( fd, NULL, 0);
+
+  /* write measurement request */
+  data[0] = 0x03; data[1] = 0x00; data[2] = 0x04;
+  ret = write( fd, data, 3 );
+  if ( ret < 0 && retry_cnt++ < 5 ) {
+    fprintf( stderr, "am2321: retry\n" );
+    udelay( 1000 );
+    goto retry;
+  }
+  if ( ret < 0 ) {
+    perror( "am2321(3)" );
+    exit( 3 );
+  }
+
+  /* wait for having measured */
+  udelay( 1500 );
+
+  /* read measured result */
+  memset( data, 0x00, 8 );
+  ret = read( fd, data, 8 );
+  if ( ret < 0 ) {
+    perror( "am2321(4)" );
+    exit( 4 );
+  }
+
+  /* close I2C device */
+  close( fd );
+
+  return __st_am2321( data );
+}
+
+st_am2321 am2321_stub() {
+  unsigned char data[] = { 0x03, 0x04, 0x01, 0x41,
+                           0x00, 0xEA, 0x21, 0x8F };
+  return __st_am2321( data );
+}
+
+
+/*
+ *  Print functions
+ */
+
+void print_am2321( st_am2321 measured ) {
+  printf( "%d.%d %d.%d\n",
+          am2321_temperature_integral( measured ),
+          am2321_temperature_fraction( measured ),
+          am2321_humidity_integral( measured ),
+          am2321_humidity_fraction( measured ) );
+  return;
+}
+
+void print_am2321_human_readable( st_am2321 measured ) {
+  printf( "Temperature (C)\t\t%d.%d\n",
+          am2321_temperature_integral( measured ),
+          am2321_temperature_fraction( measured ) );
+  printf( "Humidity (%%)\t\t%d.%d\n",
+          am2321_humidity_integral( measured ),
+          am2321_humidity_fraction( measured ) );
+  return;
+}
+
+/*
+ *  Main
+ */
+
+#define OPT_HUMAN_READABLE 0x1
+#define OPT_STUB 0x2
+
+int print_help() {
+  fprintf( stderr,
+           "Usage: am2321 [-r] [-s]\n"
+           "Get temperature and humidity measured with Aosong's AM2321 sensor.\n"
+           "  -r    human readable output\n"
+           "  -s    not measure with AM2321, instead stub of 23.4[C] and 32.1[%]\n" );
+  exit( 1 );
+}
+
+int parse_options( int argc, char* argv[]) {
+  int options = 0;
+  int flags = 0;
+
+  while( 1+flags < argc && argv[1+flags][0] == '-' ) {
+    switch( argv[1+flags][1] ) {
+    case 'r': options |= OPT_HUMAN_READABLE; break;
+    case 's': options |= OPT_STUB; break;
+    default:
+      fprintf( stderr, "am2321: Unsupported option \"%s\"\n", argv[1+flags] );
+      print_help();
+      exit( 1 );
+    }
+    flags++;
+  }
+
+  return options;
+}
+
+int is_opt_human_readable( int options ) {
+  return options & OPT_HUMAN_READABLE;
+}
+
+int is_opt_stub( int options ) {
+  return options & OPT_STUB;
+}
+
+int main( int argc, char* argv[] ) {
+  int options;
+  st_am2321 measured;
+
+  /* parse the given options */
+  options = parse_options( argc, argv );
+
+  /* measure temperature and humidity */
+  measured = ! is_opt_stub( options ) ? am2321() : am2321_stub();
+
+  /* print measured temperature and humidity */
+  if ( ! is_opt_human_readable( options ) ) {
+    print_am2321( measured );
+  } else {
+    print_am2321_human_readable( measured );
+  }
+
+  return 0;
+}
diff --git a/bh1750.c b/bh1750.c
new file mode 100644 (file)
index 0000000..798fe6c
--- /dev/null
+++ b/bh1750.c
@@ -0,0 +1,85 @@
+/*
+ Sample code for the BH1750
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <math.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+#include "smbus.h"
+
+#define BH1750FVI_I2C_ADDRESS 0x23 // ADDR > 0.7 VCC)
+//#define BH1750FVI_I2C_ADDRESS  0x53 // ADDR < 0.3 VCC)
+#define DEBUG 0
+
+#define PowerDown    0x00
+#define PowerOn    0x01
+#define Reset      0x07
+#define ContinuHigh   0x10
+#define ContinuLow   0x13
+#define OneTimeHigh   0x20
+#define OneTimeLow   0x23
+
+int main(int argc, char **argv)
+{
+    int fd;
+    char *fileName = "/dev/i2c-0";
+    int retCode;
+    int readSize;
+    unsigned int res;
+    unsigned int lux;
+    char buf[5];
+    int i;
+
+    // Open port for reading and writing
+    if ((fd = open(fileName, O_RDWR)) < 0) {
+        printf("open error\n");
+        exit(1);
+    }
+
+    // Set the port options and set the address of the device
+    if (ioctl(fd, I2C_SLAVE, BH1750FVI_I2C_ADDRESS) < 0) {
+        printf("ioctl error\n");
+        close(fd);
+        exit(1);
+    }
+
+    retCode=i2c_smbus_write_byte(fd, PowerOn);
+if(DEBUG)printf("Power On retCode=%d\n",retCode);
+    if (retCode < 0) {
+        printf("PowerOn error\n");
+        close(fd);
+        exit(1);
+    }
+
+    retCode=i2c_smbus_write_byte(fd, ContinuHigh);
+if(DEBUG)printf("ContinuHigh retCode=%d\n",retCode);
+    if (retCode < 0) {
+        printf("ContinuHigh error\n");
+        close(fd);
+        exit(1);
+    }
+
+    // Set i<10 for more one check
+    for(i=0;i<1;i++) {
+        sleep(3);
+        readSize = read (fd, buf, 2);
+if(DEBUG)printf("read readSize=%d %x %x\n",readSize,buf[0],buf[1]);
+
+        res = buf[0]*256+buf[1];
+if(DEBUG)printf("res=%x\n",res);
+        lux = res / 1.2;
+    //    printf("Lux=%d\n",lux);
+        printf("Brightness (Lux)\t%0.1f\n", ((double)lux));
+    }
+
+    retCode=i2c_smbus_write_byte(fd, PowerDown);
+    close(fd);
+
+    exit (0);
+}
\ No newline at end of file
diff --git a/bmp085.c b/bmp085.c
new file mode 100644 (file)
index 0000000..c8127dd
--- /dev/null
+++ b/bmp085.c
@@ -0,0 +1,212 @@
+/*
+ Sample code for the BMP085
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+#include "smbus.h"
+
+#define BMP085_I2C_ADDRESS 0x77
+
+const unsigned char BMP085_OVERSAMPLING_SETTING = 3;
+
+// Calibration values - These are stored in the BMP085
+short int ac1;
+short int ac2;
+short int ac3;
+unsigned short int ac4;
+unsigned short int ac5;
+unsigned short int ac6;
+short int b1;
+short int b2;
+short int mb;
+short int mc;
+short int md;
+
+int b5;
+
+unsigned int temperature, pressure;
+
+
+// Open a connection to the bmp085
+// Returns a file id
+int bmp085_i2c_Begin()
+{
+       int fd;
+       char *fileName = "/dev/i2c-0";
+
+       // Open port for reading and writing
+       if ((fd = open(fileName, O_RDWR)) < 0)
+               exit(1);
+
+       // Set the port options and set the address of the device
+       if (ioctl(fd, I2C_SLAVE, BMP085_I2C_ADDRESS) < 0) {
+               close(fd);
+               exit(1);
+       }
+
+       return fd;
+}
+
+// Read two words from the BMP085 and supply it as a 16 bit integer
+__s32 bmp085_i2c_Read_Int(int fd, __u8 address)
+{
+       __s32 res = i2c_smbus_read_word_data(fd, address);
+       if (res < 0) {
+               close(fd);
+               exit(1);
+       }
+
+       // Convert result to 16 bits and swap bytes
+       res = ((res<<8) & 0xFF00) | ((res>>8) & 0xFF);
+
+       return res;
+}
+
+//Write a byte to the BMP085
+void bmp085_i2c_Write_Byte(int fd, __u8 address, __u8 value)
+{
+       if (i2c_smbus_write_byte_data(fd, address, value) < 0) {
+               close(fd);
+               exit(1);
+       }
+}
+
+// Read a block of data BMP085
+void bmp085_i2c_Read_Block(int fd, __u8 address, __u8 length, __u8 *values)
+{
+       if(i2c_smbus_read_i2c_block_data(fd, address,length,values)<0) {
+               close(fd);
+               exit(1);
+       }
+}
+
+
+void bmp085_Calibration()
+{
+       int fd = bmp085_i2c_Begin();
+       ac1 = bmp085_i2c_Read_Int(fd,0xAA);
+       ac2 = bmp085_i2c_Read_Int(fd,0xAC);
+       ac3 = bmp085_i2c_Read_Int(fd,0xAE);
+       ac4 = bmp085_i2c_Read_Int(fd,0xB0);
+       ac5 = bmp085_i2c_Read_Int(fd,0xB2);
+       ac6 = bmp085_i2c_Read_Int(fd,0xB4);
+       b1 = bmp085_i2c_Read_Int(fd,0xB6);
+       b2 = bmp085_i2c_Read_Int(fd,0xB8);
+       mb = bmp085_i2c_Read_Int(fd,0xBA);
+       mc = bmp085_i2c_Read_Int(fd,0xBC);
+       md = bmp085_i2c_Read_Int(fd,0xBE);
+       close(fd);
+}
+
+// Read the uncompensated temperature value
+unsigned int bmp085_ReadUT()
+{
+       unsigned int ut = 0;
+       int fd = bmp085_i2c_Begin();
+
+       // Write 0x2E into Register 0xF4
+       // This requests a temperature reading
+       bmp085_i2c_Write_Byte(fd,0xF4,0x2E);
+
+       // Wait at least 4.5ms
+       usleep(5000);
+
+       // Read the two byte result from address 0xF6
+       ut = bmp085_i2c_Read_Int(fd,0xF6);
+
+       // Close the i2c file
+       close (fd);
+
+       return ut;
+}
+
+// Read the uncompensated pressure value
+unsigned int bmp085_ReadUP()
+{
+       unsigned int up = 0;
+       int fd = bmp085_i2c_Begin();
+
+       // Write 0x34+(BMP085_OVERSAMPLING_SETTING<<6) into register 0xF4
+       // Request a pressure reading w/ oversampling setting
+       bmp085_i2c_Write_Byte(fd,0xF4,0x34 + (BMP085_OVERSAMPLING_SETTING<<6));
+
+       // Wait for conversion, delay time dependent on oversampling setting
+       usleep((2 + (3<<BMP085_OVERSAMPLING_SETTING)) * 1000);
+
+       // Read the three byte result from 0xF6
+       // 0xF6 = MSB, 0xF7 = LSB and 0xF8 = XLSB
+       __u8 values[3];
+       bmp085_i2c_Read_Block(fd, 0xF6, 3, values);
+
+       up = (((unsigned int) values[0] << 16) | ((unsigned int) values[1] << 8) | (unsigned int) values[2]) >> (8-BMP085_OVERSAMPLING_SETTING);
+
+       return up;
+}
+
+// Calculate pressure given uncalibrated pressure
+// Value returned will be in units of XXXXX
+unsigned int bmp085_GetPressure(unsigned int up)
+{
+       int x1, x2, x3, b3, b6, p;
+       unsigned int b4, b7;
+
+       b6 = b5 - 4000;
+       // Calculate B3
+       x1 = (b2 * (b6 * b6)>>12)>>11;
+       x2 = (ac2 * b6)>>11;
+       x3 = x1 + x2;
+       b3 = (((((int)ac1)*4 + x3)<<BMP085_OVERSAMPLING_SETTING) + 2)>>2;
+
+       // Calculate B4
+       x1 = (ac3 * b6)>>13;
+       x2 = (b1 * ((b6 * b6)>>12))>>16;
+       x3 = ((x1 + x2) + 2)>>2;
+       b4 = (ac4 * (unsigned int)(x3 + 32768))>>15;
+
+       b7 = ((unsigned int)(up - b3) * (50000>>BMP085_OVERSAMPLING_SETTING));
+       if (b7 < 0x80000000)
+               p = (b7<<1)/b4;
+       else
+               p = (b7/b4)<<1;
+
+       x1 = (p>>8) * (p>>8);
+       x1 = (x1 * 3038)>>16;
+       x2 = (-7357 * p)>>16;
+       p += (x1 + x2 + 3791)>>4;
+
+       return p;
+}
+
+// Calculate temperature given uncalibrated temperature
+// Value returned will be in units of 0.1 deg C
+unsigned int bmp085_GetTemperature(unsigned int ut)
+{
+       int x1, x2;
+
+       x1 = (((int)ut - (int)ac6)*(int)ac5) >> 15;
+       x2 = ((int)mc << 11)/(x1 + md);
+       b5 = x1 + x2;
+
+       unsigned int result = ((b5 + 8)>>4);  
+
+       return result;
+}
+
+int main(int argc, char **argv)
+{
+       bmp085_Calibration();
+       temperature = bmp085_GetTemperature(bmp085_ReadUT());
+       pressure = bmp085_GetPressure(bmp085_ReadUP());
+
+       printf("Temperature (C)\t\t%0.1f\n", ((double)temperature)/10);
+       printf("Pressure (mBar)\t%0.2f\n", ((double)pressure)/100);
+       // printf("Pressure (mmHg)\t%0.2f\n", ((double)pressure)/100*0.75006375541921);
+       // printf("Pressure (mmHg)\t\t%0.2f\n", ((double)pressure)/100*0.750061683);
+       return 0;
+}
\ No newline at end of file
diff --git a/ds1621.c b/ds1621.c
new file mode 100644 (file)
index 0000000..30e858e
--- /dev/null
+++ b/ds1621.c
@@ -0,0 +1,134 @@
+/* Test DS1621 sur interface I2C GPIO Fonera (3/2008)                                  */
+/* Inspir de "Un bus i2c pour La Fonera"                                               */
+/* http://www.lefinnois.net/wp/index.php/2007/05/05/un-bus-i2c-pour-la-fonera/         */
+
+/* Affichage de la t                                                                   */
+/* Par domos domos78<at>free<point>fr                                                  */
+/* http://vesta.homelinux.net/                                                         */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+
+#define I2C_SLAVE       0x0703         // Change slave address
+
+static int i2c_fd ;
+int res ;
+
+#define DEVICE "/dev/i2c-0"
+#define ds1621_addr 0x9E >> 1          // 0x4f - Address (A0+A1+A2 to Vcc)
+
+
+/*------------------------------------------------------------------------------*/
+/* Fonctions i2c                                                               */
+/*------------------------------------------------------------------------------*/
+void i2c_init()
+{
+       if ((i2c_fd = open(DEVICE, O_RDWR)) < 0) 
+       {
+               fprintf(stderr, "Erreur ouverture port: %s (%d)\n", strerror(errno), errno);
+               exit(EXIT_FAILURE);
+       }
+}
+
+//-----------------------------------------------------------------------------
+void SelectSlave(unsigned char slaveaddr)
+{
+       if (ioctl(i2c_fd, I2C_SLAVE, slaveaddr) < 0) 
+       {
+               fprintf(stderr, "Erreur selection esclave i2c: %s (%d)\n", strerror(errno), errno);
+               close ( i2c_fd ) ;
+               exit(EXIT_FAILURE) ;
+       } 
+}
+
+/*------------------------------------------------------------------------------*/
+/* Fonctions DS1621                                                            */
+/*------------------------------------------------------------------------------*/
+int i2c_init_ds1621(unsigned char addr)
+{
+       int res ;
+       char buff[10] ;
+       
+       SelectSlave(addr) ;
+       buff[0] = 0xAC ;
+       buff[1] = 0x01 ;
+       res = write( i2c_fd, buff, 2 );
+       if ( res < 0 )
+       {
+               printf("Erreur init DS1621 addr 0x%x: '%s', Abandon programme !", addr, strerror(errno));
+               close ( i2c_fd );
+               exit(1) ;
+       }
+       /* start temperature conversion */
+       errno = 0 ;     
+       buff[0] = 0xEE ;
+       write( i2c_fd, buff, 1 );
+       sleep(1) ;
+       return 1 ;
+}
+
+//-----------------------------------------------------------------------------
+double i2c_gettemp_ds1621(unsigned char addr)
+{
+       int k, count, slope, temp;
+       char buff[10] ;
+       
+       SelectSlave(addr) ;
+       /* stop conversion */
+       errno = 0 ;     
+       buff[0] = 0x22 ;
+
+       if ( write( i2c_fd, buff, 1 ) < 0 ) return 255 ; // Write retourne -1 et strerror(errno))='Remote I/O error' si adr. i2c non connecte.
+       else
+       {
+               /* Temperature reading (1 Celsius degree precision) */
+               buff[0] = 0xAA ;
+               write( i2c_fd, buff, 1 );
+               read(i2c_fd, buff, 1) ;
+               temp = buff[0] ;
+               /* Counter reading (fraction of degree) ) */
+               buff[0] = 0xA8 ;
+               write( i2c_fd, buff, 1 );
+               read(i2c_fd, buff, 1) ;
+               count = buff[0] ;
+               /* slope reading */
+               buff[0] = 0xA9 ;
+               write( i2c_fd, buff, 1 );
+               read(i2c_fd, buff, 1) ;
+               slope = buff[0] ;
+               k = temp;
+               if (slope != 0) 
+               {
+                       k = temp*100-25+(100*(slope-count))/slope;
+               }
+               /* start temperature conversion */
+               buff[0] = 0xEE ;
+               write( i2c_fd, buff, 1 );
+               return (float)k/100 ;
+       }
+}
+
+/*------------------------------------------------------------------------------*/
+int main ( int argc, char ** argv )
+{
+       // Init i2c.
+       i2c_init() ;
+
+       // Init ds1621.
+       i2c_init_ds1621(ds1621_addr) ;
+
+       // Affiche la t.
+       printf("%2.1f\n", i2c_gettemp_ds1621(ds1621_addr) ) ;
+
+       close ( i2c_fd );
+}
+
+/*------------------------------------------------------------------------------*/
+
diff --git a/etraxi2c.h b/etraxi2c.h
new file mode 100644 (file)
index 0000000..9d5c9bf
--- /dev/null
@@ -0,0 +1,49 @@
+#ifndef _LINUX_ETRAXI2C_H
+#define _LINUX_ETRAXI2C_H
+
+/* etraxi2c _IOC_TYPE, bits 8 to 15 in ioctl cmd */
+
+#define ETRAXI2C_IOCTYPE 44
+
+/* supported ioctl _IOC_NR's */
+
+/* in write operations, the argument contains both i2c
+ * slave, register and value.
+ */
+
+#define I2C_WRITEARG(slave, reg, value) (((slave) << 16) | ((reg) << 8) | (value))
+#define I2C_READARG(slave, reg) (((slave) << 16) | ((reg) << 8))
+
+#define I2C_ARGSLAVE(arg) ((arg) >> 16)
+#define I2C_ARGREG(arg) (((arg) >> 8) & 0xff)
+#define I2C_ARGVALUE(arg) ((arg) & 0xff)
+
+#define I2C_WRITEREG    0x1   /* write to an I2C register */
+#define I2C_READREG     0x2   /* read from an I2C register */
+
+/*
+EXAMPLE usage:
+
+    i2c_arg = I2C_WRITEARG(STA013_WRITE_ADDR, reg, val);
+    ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_WRITEREG), i2c_arg);
+
+    i2c_arg = I2C_READARG(STA013_READ_ADDR, reg);
+    val = ioctl(fd, _IO(ETRAXI2C_IOCTYPE, I2C_READREG), i2c_arg);
+
+*/
+
+/* Extended part */
+#define I2C_READ        0x4     /* reads from I2C device */
+#define I2C_WRITE       0x3     /* writes to I2C device */
+#define I2C_WRITEREAD   0x5        /* writes to I2C device where to start reading */
+
+typedef struct _I2C_DATA 
+{
+    unsigned char slave;        /* I2C address (8-bit representation) of slave device */
+    unsigned char wbuf[256];    /* Write buffer (length = 256 bytes) */
+       unsigned int  wlen;         /* Number of bytes to write from wbuf[] */   
+       unsigned char rbuf[256];    /* Read buffer (length = 256 bytes) */
+    unsigned int  rlen;         /* Number of bytes to read into rbuf[] */
+} I2C_DATA;
+
+#endif
diff --git a/gethwclock b/gethwclock
new file mode 100644 (file)
index 0000000..27265d5
--- /dev/null
@@ -0,0 +1,13 @@
+#!/bin/sh
+
+I2CBUS=0
+I2CADDR=0x68
+
+sec=`i2cget -y $I2CBUS $I2CADDR 0`
+min=`i2cget -y $I2CBUS $I2CADDR 1`
+hour=`i2cget -y $I2CBUS $I2CADDR 2`
+day=`i2cget -y $I2CBUS $I2CADDR 4`
+month=`i2cget -y $I2CBUS $I2CADDR 5`
+year=`i2cget -y $I2CBUS $I2CADDR 6`
+
+echo 20${year:2:2}-${month:2:2}-${day:2:2} ${hour:2:2}:${min:2:2}:${sec:2:2}
diff --git a/i2c_errno.h b/i2c_errno.h
new file mode 100644 (file)
index 0000000..a517b6f
--- /dev/null
@@ -0,0 +1,20 @@
+#ifndef _I2C_ERRNO_H
+#define _I2C_ERRNO_H
+
+#define EI2CNOERRORS  0     /* All fine */
+#define EI2CBUSNFREE  1     /* I2C bus not free */
+#define EI2CWADDRESS  2     /* Address write failed */
+#define EI2CRADDRESS  3     /* Address read failed */
+#define EI2CSENDDATA  4     /* Sending data failed */
+#define EI2CRECVDATA  5     /* Receiving data failed */
+#define EI2CSTRTCOND  6     /* Start condition failed */
+#define EI2CRSTACOND  7     /* Repeated start condition failed */
+#define EI2CSTOPCOND  8     /* Stop condition failed */
+#define EI2CNOSNDBYT  9     /* Number of send bytes is 0, while there's a send buffer defined */
+#define EI2CNOSNDBUF  10    /* No send buffer defined, while number of send bytes is not 0 */
+#define EI2CNORCVBYT  11    /* Number of receive bytes is 0, while there's a receive buffer defined */
+#define EI2CNORCVBUF  12    /* No receive buffer defined, while number of receive bytes is not 0 */
+#define EI2CNOACKNLD  13    /* No acknowledge received from slave */
+#define EI2CNOMNUMBR  14    /* No MAJOR number received from kernel while registering the device */
+
+#endif /* _I2C_ERRNO_H */
diff --git a/i2cget_bmp180.example b/i2cget_bmp180.example
new file mode 100644 (file)
index 0000000..828d16b
--- /dev/null
@@ -0,0 +1,17 @@
+#!/bin/sh
+#
+# More info: http://cyber-place.ru/showpost.php?p=7797&postcount=82
+
+RAWTEMP=$(i2cget -y 0 0x40 0xe3 w)
+RAWHUMI=$(i2cget -y 0 0x40 0xe5 w)
+
+if (echo "$RAWTEMP"| grep -Eq '0x[0-9a-f]{4}'); then
+   HEXORDERED=$(echo "$RAWTEMP"|sed -r 's/0x([0-9a-f]{2})([0-9a-f]{2})/0x\2\1/')
+   DECRAW=$(($HEXORDERED))
+   echo $DECRAW | awk -v tem=${DECRAW} '{ printf "%.2f stC\n", -46.85+((tem*175.72)/65536)}'
+fi
+if (echo "$RAWHUMI"| grep -Eq '0x[0-9a-f]{4}'); then
+   HEXORDERED=$(echo "$RAWHUMI"|sed -r 's/0x([0-9a-f]{2})([0-9a-f]{2})/0x\2\1/')
+   DECRAW=$(($HEXORDERED))
+   echo $DECRAW | awk -v hum=${DECRAW} '{ printf "%.2f %%RH\n", -6+((hum*125)/65536)}'
+fi
\ No newline at end of file
diff --git a/ina219.c b/ina219.c
new file mode 100644 (file)
index 0000000..9cf3de6
--- /dev/null
+++ b/ina219.c
@@ -0,0 +1,400 @@
+/*
+* INA219 util - part of PowerCape by AndiceLabs
+*
+* Copyright (C) 2014  AndiceLabs admin@andicelabs.com  http://andicelabs.com
+* Copyright (C) 2014  Zig Fisher flyrouter@gmail.com   http://zftlab.org
+*
+* This program is free software; you can redistribute it and/or
+* modify it under the terms of the GNU General Public License
+* as published by the Free Software Foundation; either version 2
+* of the License, or (at your option) any later version.
+*
+* This program is distributed in the hope that it will be useful,
+* but WITHOUT ANY WARRANTY; without even the implied warranty of
+* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+* GNU General Public License for more details.
+*
+*
+* Example run and output:
+*
+* OpenWRT:~# ina219 -b 0 -i 60
+*
+* 22:49 12168mV  134.2mA
+* 22:50 12168mV  239.9mA
+* 22:51 12168mV  134.7mA
+*
+*/
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <endian.h>
+#include <string.h>
+#include <time.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/i2c-dev.h>
+
+#define CONFIG_REG          0
+#define SHUNT_REG           1
+#define BUS_REG             2
+#define POWER_REG           3
+#define CURRENT_REG         4
+#define CALIBRATION_REG     5
+
+#define AVR_ADDRESS         0x21
+#define INA_ADDRESS         0x40
+
+typedef enum {
+    OP_DUMP,
+    OP_VOLTAGE,
+    OP_CURRENT,
+    OP_MONITOR,
+    OP_NONE
+} op_type;
+
+op_type operation = OP_DUMP;
+
+int interval = 60;
+int i2c_bus = 0;
+int i2c_address = INA_ADDRESS;
+int handle;
+int whole_numbers = 0;
+
+
+void msleep( int msecs )
+{
+    usleep( msecs * 1000 );
+}
+
+
+int i2c_read( void *buf, int len )
+{
+    int rc = 0;
+
+    if ( read( handle, buf, len ) != len )
+    {
+        printf( "I2C read failed: %s\n", strerror( errno ) );
+        rc = -1;
+    }
+
+    return rc;
+}
+
+
+int i2c_write( void *buf, int len )
+{
+    int rc = 0;
+
+    if ( write( handle, buf, len ) != len ) 
+    {
+        printf( "I2C write failed: %s\n", strerror( errno ) );
+        rc = -1;
+    }
+
+    return rc;
+}
+
+
+int register_read( unsigned char reg, unsigned short *data )
+{
+    int rc = -1;
+    unsigned char bite[ 4 ];
+
+    bite[ 0 ] = reg;
+    if ( i2c_write( bite, 1 ) == 0 )
+    {
+        if ( i2c_read( bite, 2 ) == 0 )
+        {
+            *data = ( bite[ 0 ] << 8 ) | bite[ 1 ];
+            rc = 0;
+        }
+    }
+
+    return rc;
+}
+
+
+int register_write( unsigned char reg, unsigned short data )
+{
+    int rc = -1;
+    unsigned char bite[ 4 ];
+
+    bite[ 0 ] = reg;
+    bite[ 1 ] = ( data >> 8 ) & 0xFF;
+    bite[ 2 ] = ( data & 0xFF );
+
+    if ( i2c_write( bite, 3 ) == 0 )
+    {
+        rc = 0;
+    }
+
+    return rc;
+}
+
+
+void show_usage( char *progname )
+{
+    fprintf( stderr, "Usage: %s <mode> \n", progname );
+    fprintf( stderr, "   Mode (required):\n" );
+    fprintf( stderr, "      -h --help           Show usage.\n" );
+    fprintf( stderr, "      -i --interval       Set interval for monitor mode.\n" );
+    fprintf( stderr, "      -w --whole          Show whole numbers only. Useful for scripts.\n" );
+    fprintf( stderr, "      -v --voltage        Show battery voltage in mV.\n" );
+    fprintf( stderr, "      -c --current        Show battery current in mA.\n" );
+    fprintf( stderr, "      -a --address <addr> Override I2C address of INA219 from default of 0x%02X.\n", i2c_address );
+    fprintf( stderr, "      -b --bus <i2c bus>  Override I2C bus from default of %d.\n", i2c_bus );
+    exit( 1 );
+}
+
+
+void parse( int argc, char *argv[] )
+{
+    while( 1 )
+    {
+        static const struct option lopts[] =
+        {
+            { "address",    0, 0, 'a' },
+            { "bus",        0, 0, 'b' },
+            { "current",    0, 0, 'c' },
+            { "help",       0, 0, 'h' },
+            { "interval",   0, 0, 'i' },
+            { "voltage",    0, 0, 'v' },
+            { "whole",      0, 0, 'w' },
+            { NULL,         0, 0, 0 },
+        };
+        int c;
+
+        c = getopt_long( argc, argv, "a:b:chi:vw", lopts, NULL );
+
+        if( c == -1 )
+            break;
+
+        switch( c )
+        {
+            case 'a':
+            {
+                errno = 0;
+                i2c_address = (int)strtol( optarg, NULL, 0 );
+                if ( errno != 0 )
+                {
+                    fprintf( stderr, "Unknown address parameter %s.\n", optarg );
+                    exit( 1 );
+                }
+                break;
+            }
+
+            case 'b':
+            {
+                errno = 0;
+                i2c_bus = (int)strtol( optarg, NULL, 0 );
+                if ( errno != 0 )
+                {
+                    fprintf( stderr, "Unknown bus parameter %s.\n", optarg );
+                    exit( 1 );
+                }
+                break;
+            }
+
+            case 'c':
+            {
+                operation = OP_CURRENT;
+                break;
+            }
+
+            default:
+            case 'h':
+            {
+                operation = OP_NONE;
+                show_usage( argv[ 0 ] );
+                break;
+            }
+
+            case 'i':
+            {
+                operation = OP_MONITOR;
+                interval = atoi( optarg );
+                if ( ( interval == 0 ) && ( errno != 0 ) )
+                {
+                    fprintf( stderr, "Invalid interval value\n" );
+                    exit( 1 );
+                }
+                break;
+            }
+
+            case 'v':
+            {
+                operation = OP_VOLTAGE;
+                break;
+            }
+
+            case 'w':
+            {
+                whole_numbers = 1;
+                break;
+            }
+        }
+    }
+}
+
+
+int get_voltage( float *mv )
+{
+    short bus;
+
+    if ( register_read( BUS_REG, (unsigned short*)&bus ) != 0 )
+    {
+        return -1;
+    }
+
+    *mv = ( float )( ( bus & 0xFFF8 ) >> 1 );
+    return 0;
+}
+
+
+int get_current( float *ma )
+{
+    short shunt;
+
+    if ( register_read( SHUNT_REG, &shunt ) != 0 )
+    {
+        return -1;
+    }
+
+    *ma = (float)shunt / 10;
+    return 0;
+}
+
+
+void show_current( void )
+{
+    float ma;
+
+    if ( get_current( &ma ) )
+    {
+        fprintf( stderr, "Error reading current\n" );
+        return;
+    }
+
+    if ( whole_numbers )
+    {
+        printf( "%4.0f\n", ma );
+    }
+    else
+    {
+        printf( "%04.1f\n", ma );
+    }
+}
+
+
+void show_voltage( void )
+{
+    float mv;
+
+    if ( get_voltage( &mv ) )
+    {
+        fprintf( stderr, "Error reading voltage\n" );
+        return;
+    }
+    printf( "%4.0f\n", mv );
+}
+
+
+void show_voltage_current( void )
+{
+    float mv, ma;
+
+    if ( get_current( &ma ) || get_voltage( &mv ) )
+    {
+        fprintf( stderr, "Error reading voltage/current\n" );
+        return;
+    }
+
+    if ( whole_numbers )
+    {
+        printf( "%04.0fmV  %4.0fmA\n", mv, ma );
+    }
+    else
+    {
+        printf( "%04.0fmV  %04.1fmA\n", mv, ma );
+    }
+}
+
+
+void monitor( void )
+{
+    struct tm *tmptr;
+    time_t seconds;
+
+    while ( 1 )
+    {
+        seconds = time( NULL );
+        tmptr = localtime( &seconds );
+        printf( "%02d:%02d ", tmptr->tm_hour, tmptr->tm_min );
+        show_voltage_current();
+        sleep( interval );
+    }
+}
+
+
+int main( int argc, char *argv[] )
+{
+    char filename[ 20 ];
+
+    parse( argc, argv );
+
+    snprintf( filename, 19, "/dev/i2c-%d", i2c_bus );
+    handle = open( filename, O_RDWR );
+    if ( handle < 0 ) 
+    {
+        fprintf( stderr, "Error opening bus %d: %s\n", i2c_bus, strerror( errno ) );
+        exit( 1 );
+    }
+
+    if ( ioctl( handle, I2C_SLAVE, i2c_address ) < 0 ) 
+    {
+        fprintf( stderr, "Error setting address %02X: %s\n", i2c_address, strerror( errno ) );
+        exit( 1 );
+    }
+
+    switch ( operation )
+    {
+        case OP_DUMP:
+        {
+            show_voltage_current();
+            break;
+        }
+
+        case OP_VOLTAGE:
+        {
+            show_voltage();
+            break;
+        }
+
+        case OP_CURRENT:
+        {
+            show_current();
+            break;
+        }
+
+        case OP_MONITOR:
+        {
+            monitor();
+            break;
+        }
+
+        default:
+        case OP_NONE:
+        {
+            break;
+        }
+    }
+
+    close( handle );
+    return 0;
+}
+
diff --git a/lcdd.c b/lcdd.c
new file mode 100644 (file)
index 0000000..8cdd85f
--- /dev/null
+++ b/lcdd.c
@@ -0,0 +1,394 @@
+/* Simple daemon to communicate with Newhaven I2C LCD module.
+ *
+ * This is a trivial interface for Newhaven LCD module connected to a Linux machine
+ * over an I2C interface. Any standard Linux I2C bus should work (including USB I2C
+ * adapters that correctly hook into the i2c kernel driver framework).
+ *
+ * Opens a named pipe at /dev/lcd which can be written to by other applications.
+ * Text written to this file will appear on the LCD.
+ * Send a bell ('\b')to clear the screen.
+ *
+ * Tested with NHD-0420D3Z-FL-GBW (Digikey part number NHD-0420D3Z-FL-GBW-ND).
+ * http://www.newhavendisplay.com/specs/NHD-0420D3Z-FL-GBW.pdf
+ * http://www.newhavendisplay.com/index.php?main_page=product_info&cPath=253&products_id=922
+ *
+ * FIXME how to do other commands etc.
+ * FIXME some rate limiting should be added... the I2C controller on the LCD
+ * module gets confused if you write to it too fast.
+ *
+ * Hardware note:
+ * To enable I2C mode of LCD, Pads of R1 must be jumpered on back of LCD
+ * See the manual for the LCD module.
+ *
+ * ./lcdd -a 0x47 -d /dev/i2c-4 -f /dev/lcd -n
+ *
+ * Hugo Vincent, June 2009 - https://github.com/hugovincent/i2c-lcdd
+ * Daemonization based on code by Peter Lombardo <peter@lombardo.info>, 2006
+ */
+
+
+#define _GNU_SOURCE // for strsignal()
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <stdint.h>
+#include <errno.h>
+#include <syslog.h>
+#include <assert.h>
+#include <signal.h>
+#include <poll.h>
+#include <setjmp.h>
+#include <linux/i2c-dev.h>
+
+#define DAEMON_NAME "lcdd"
+#define PID_FILE "/var/run/lcdd.pid"
+
+#define LCD_ADDR 0x27
+
+//#define DEBUG
+
+static int daemonize = 1, running = 1, have_lcd = 1;
+static jmp_buf my_jmp_buf;
+
+#define LOG_MSG(format, ...) if (daemonize == 1) \
+                                                                                       syslog(LOG_INFO, format, ##__VA_ARGS__); \
+else \
+printf("i2c-lcdd: " format "\n", ##__VA_ARGS__);
+
+void usage(int argc, char **argv)
+{
+       if (argc >=1)
+       {
+               printf("Usage: %s -a 0x50 -d /dev/i2c-3 -f /dev/lcd -n -?\n", argv[0]);
+               printf("  Options:\n");
+               printf("     -a\tI2C slave address (in hex) for LCD module\n");
+               printf("     -d\tI2C device\n");
+               printf("     -f\tnamed pipe for input\n");
+               printf("     -n\tDon't daemonize.\n");
+               printf("     -?\tShow this help screen.\n");
+       }
+}
+
+void signal_handler(int sig)
+{ 
+       LOG_MSG("received signal %s - exiting", strsignal(sig));
+       running = 0;
+}
+
+void i2c_send(int fd, uint8_t *buf, int count)
+{
+       if (have_lcd)
+       {
+               if (write(fd, buf, count) != count)
+               {
+                       LOG_MSG("error writing to I2C: %s", strerror(errno));
+                       longjmp(my_jmp_buf, EXIT_FAILURE);
+                       //exit(EXIT_FAILURE);
+               }
+       }
+       else
+       {
+#ifdef DEBUG
+               static char tmp[1024];
+               strncpy(tmp, buf, count);
+               tmp[count] = 0;
+               printf("I2C send: \"%s\"\n", tmp);
+#endif
+       }
+}
+
+uint8_t linenum_to_cursor(int linenum)
+{
+       switch (linenum)
+       {
+               case 1:
+                       return 0x40;
+                       break;
+               case 2:
+                       return 0x14;
+                       break;
+               case 3:
+                       return 0x54;
+                       break;
+               case 0:
+               default:
+                       return 0x0;
+                       break;
+       }
+}
+
+#define min(a, b) ((a <= b) ? a : b)
+
+void handle_pipe_input(int i2c_fd, char *buffer, int size)
+{
+       // FIXME this should handle escape sequences (other than \b, \n) too
+
+       static int line_number = 0;
+
+       // LCD clear
+       if (size >= 1 && buffer[0] == '\b')
+       {
+               uint8_t bytes[] = {0xFE, 0x51};
+               i2c_send(i2c_fd, bytes, sizeof(bytes));
+               buffer++; size--;
+               line_number = 0;
+       }
+
+       // Split input into lines
+       char *line = strtok(buffer, "\n");
+       while (line != NULL)
+       {
+               // Because of weird cursor positioning on the LCD module, if we write
+               // more than 20 characters on line 1 it'll flow over onto line 3, (or
+               // off line 2 on to line 4). Thus, we limit lines to 20 chars.
+
+               i2c_send(i2c_fd, line, min(strlen(line), 20));
+               line_number = (line_number < 3) ? (line_number + 1) : 0;
+
+               // Go to specified line
+               uint8_t bytes[] = {0xFE, 0x45, 0x0};
+               bytes[2] = linenum_to_cursor(line_number);
+               i2c_send(i2c_fd, bytes, sizeof(bytes));
+
+               // Get next line
+               line = strtok(NULL, "\n");
+       }
+}
+
+int main(int argc, char **argv)
+{
+       char device[64] = "/dev/i2c-3", fifo_name[64] = "/dev/lcd";
+       int addr = LCD_ADDR, addr_sscanf_ret = 1;
+
+       // Setup signal handling before we start
+       signal(SIGHUP, signal_handler);
+       siginterrupt(SIGHUP, 1);
+       signal(SIGQUIT, signal_handler);
+       siginterrupt(SIGQUIT, 1);
+       signal(SIGTERM, signal_handler);
+       siginterrupt(SIGTERM, 1);
+       signal(SIGINT, signal_handler);
+       siginterrupt(SIGINT, 1);
+
+       int c;
+       while( (c = getopt(argc, argv, "a:d:f:n?")) != -1) {
+               switch(c){
+                       case 'a':
+                               addr_sscanf_ret = sscanf(optarg, "0x%x", &addr);
+                               break;
+                       case 'd':
+                               strncpy(device, optarg, sizeof(device));
+                               break;
+                       case 'f':
+                               strncpy(fifo_name, optarg, sizeof(fifo_name));
+                               break;
+                       case 'n':
+                               daemonize = 0;
+                               break;
+                       case '?':
+                       default:
+                               usage(argc, argv);
+                               exit(0);
+                               break;
+               }
+       }
+
+       // Setup syslog logging
+       if (daemonize == 1)
+       {
+               setlogmask(LOG_UPTO(LOG_INFO));
+               openlog(DAEMON_NAME, LOG_CONS, LOG_USER);
+       }
+       LOG_MSG("daemon starting up");
+
+       // Check sscanf above worked (delayed until after syslog is initialized)
+       if (addr_sscanf_ret != 1)
+               LOG_MSG("supplied address invalid, using 0x%02x", addr);
+
+       // Our process ID and Session ID
+       pid_t pid, sid;
+
+       if (daemonize)
+       {
+               // Fork off the parent process
+               pid = fork();
+               if (pid < 0)
+               {
+                       LOG_MSG("failed to fork daemon process");
+                       exit(EXIT_FAILURE);
+               }
+
+               // If we got a good PID, then we can exit the parent process
+               if (pid > 0)
+                       exit(EXIT_SUCCESS);
+
+               // Change the file mode mask
+               umask(0);
+
+               // Create a new SID for the child process
+               sid = setsid();
+               if (sid < 0)
+               {
+                       LOG_MSG("failed to set daemon process SID");
+                       exit(EXIT_FAILURE);
+               }
+
+               // Change the current working directory
+               if ((chdir("/")) < 0)
+               {
+                       LOG_MSG("failed to change daemon working directory");
+                       exit(EXIT_FAILURE);
+               }
+
+               // Close out the standard file descriptors
+               close(STDIN_FILENO);
+#ifndef DEBUG
+               close(STDOUT_FILENO);
+#endif
+               close(STDERR_FILENO);
+       }
+
+       //************************************************************************
+
+       addr >>= 1; // to suit LCD addressing sematics of Newhaven LCD modules
+
+       // Initialise FIFO on which to accept input
+       if (mkfifo(fifo_name, S_IRWXU) < 0)
+       {
+               if (errno != EEXIST)
+               {
+                       LOG_MSG("error creating named pipe for input: %s", strerror(errno));
+                       exit(EXIT_FAILURE);
+               }
+               else
+               {
+                       LOG_MSG("warning, named pipe already exists: %s", strerror(errno));
+                       // FIXME unlink and reopen
+               }
+       }
+
+       // Connect to I2C LCD and set slave address
+       int i2c_fd = open(device, O_RDWR);
+       if (i2c_fd < 0)
+       {
+               LOG_MSG("error opening device: %s", strerror(errno));
+               have_lcd = 0;
+               goto nolcd;
+       }
+       if (ioctl(i2c_fd, I2C_SLAVE, addr) < 0) 
+       {
+               LOG_MSG("error setting I2C slave address: %s", strerror(errno));
+               close(i2c_fd);
+               have_lcd = 0;
+       }
+
+nolcd:
+       if (setjmp(my_jmp_buf) == EXIT_FAILURE)
+               goto exit1;
+
+       if (!have_lcd)
+       {
+               LOG_MSG("could not open I2C LCD, printing to stdout for debugging");
+       }
+       else
+       {
+               LOG_MSG("using Nehaven LCD attached to %s at real address 0x%x", device, addr);
+
+               // Initialise LCD
+               uint8_t bytes[] = {0xFE, 0x41};         // LCD on
+               i2c_send(i2c_fd, bytes, sizeof(bytes));
+               bytes[1] = 0x51;                                        // LCD clear
+               i2c_send(i2c_fd, bytes, sizeof(bytes));
+
+               uint8_t *string = (uint8_t*)"  Initialising...";
+               i2c_send(i2c_fd, string, strlen((char*)string));
+       }
+
+       char buffer[256];
+       int fifo_fd = -1;
+       struct pollfd fds = { .events = POLLIN };
+
+       // Main Loop: read on named pipe, output on LCD
+       while (running)
+       {
+               if (fifo_fd == -1)
+               {
+#ifdef DEBUG
+                       LOG_MSG("waiting for connection on %s...", fifo_name);
+#endif
+                       fifo_fd = open(fifo_name, O_RDONLY); // this will block until other end of pipe is opened
+                       if (fifo_fd < 0)
+                       {
+                               if (errno == EINTR)
+                                       continue;
+                               LOG_MSG("error opening named pipe for input: %s", strerror(errno));
+                               goto exit3;
+                       }
+                       fds.fd = fifo_fd;
+#ifdef DEBUG
+                       LOG_MSG("connected, accepting input on %s", fifo_name);
+#endif
+               }
+
+               // Wait for input on the named pipe
+               int poll_ret = poll(&fds, 1, 1000);
+               if (poll_ret == 1 && fds.revents | POLLIN)
+               {
+                       memset(&buffer, 0, sizeof(buffer));
+                       int bytes_read = read(fifo_fd, &buffer, sizeof(buffer));
+
+                       // Write input to LCD
+                       if (bytes_read > 0)
+                               handle_pipe_input(i2c_fd, buffer, bytes_read);
+                       else if (bytes_read == 0)
+                       {
+#ifdef DEBUG
+                               LOG_MSG("named pipe closed");
+#endif
+                               close(fifo_fd);
+                               fifo_fd = -1;
+                       }
+                       else
+                       {
+                               LOG_MSG("error reading from named pipe: %s", strerror(errno));
+                               goto exit1;
+                       }
+               }
+               else if (poll_ret < 0 && running)
+               {
+                       LOG_MSG("error waiting for input on named pipe: %s", strerror(errno));
+                       goto exit1;
+               }
+               else
+               {
+                       // Timeout in poll(), no need to worry (timeout is only enabled as insurance anyway)
+               }
+       }
+
+       LOG_MSG("daemon exiting cleanly");
+
+       close(fifo_fd);
+       unlink(fifo_name);
+       if (have_lcd)
+               close(i2c_fd);
+
+       return 0;
+
+       // Cleanup on error
+exit1:
+       if (have_lcd)
+               close(i2c_fd);
+exit2:
+       close(fifo_fd);
+exit3:
+       unlink(fifo_name);
+       LOG_MSG("daemon exiting with failure");
+       exit(EXIT_FAILURE);
+}
+
diff --git a/lm75.c b/lm75.c
new file mode 100644 (file)
index 0000000..499ded5
--- /dev/null
+++ b/lm75.c
@@ -0,0 +1,49 @@
+  /*
+    LM75_address.c
+    --------------
+      1) set the i2c address of the LM75
+       * R/W pulse at end of address byte not included in address 1-0-0-1-A2-A1-A0
+       * example - all lines to 0V - 1001000 = decimal 72
+      2) calculate the temperature
+      3) print it
+       usage :- type (without the < >)
+               <LM75_address><space><address as decimal>
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+#include "smbus.h"
+
+int main(int argc, char** argv)
+{
+  int address;      /* i2c bus address */
+
+ if (argc != 2)   /* report error if we are not getting just 1 input after the program name */
+ {
+  printf("Error. usage: %s i2c_chip_address\n", argv[0]);
+ }
+  address = atoi(argv[1]); /* address is the first number after the program name */
+
+
+          int f = open("/dev/i2c-0",O_RDWR);
+          char buf[2];
+          if (f>0) {
+              ioctl(f,I2C_SLAVE,address);
+              if (-1 == read(f,buf,2)) {
+                  printf("read error.\n");
+              } else { /* calculate the temperature*/
+                  int temp = buf[0]*256+buf[1];
+                  temp >>=7;
+                  if (temp>512)
+                      temp &= -1;
+                  printf("Temperature (C)\t\t%g\n", (float)temp/2.0);
+              }
+          }
+          return close(f);
+      }
diff --git a/mcp_rw.c b/mcp_rw.c
new file mode 100644 (file)
index 0000000..81bf7cd
--- /dev/null
+++ b/mcp_rw.c
@@ -0,0 +1,297 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <sys/ioctl.h>
+#include <string.h>
+// Строки ниже необходимы для rasbian/debian.В Suse должны быть закаментированы.
+#include <linux/i2c.h>
+#include "smbus.h" 
+
+#define mcp_I2C_ADDRESS 0x20 // адрес устройства в сети i2c,задается перемычками A0,A1,A2 на микросхеме.
+
+
+// ниже 2 строки задают направление порта ,1 - на ввод,0 - на вывод.
+#define mcp_bank_a 0b00000100  //байты 7 по 0 порт
+#define mcp_bank_b 0b00000000 //байты 8 по 15 порт
+// следущие 2 строки-подтяжка резистором 100 кОм на +, 1 - включен.Актуально для режима на ввод.
+#define gppu_bank_a 0b00000100 //байты 7 по 0 порт
+#define gppu_bank_b 0b00000000 //байты 8 по 15 порт
+// регистры 02 03 для инвертирования
+#define iopol_bank_a 0b00000110 //байты 7 по 0 порт
+#define iopol_bank_b 0b00000000 //байты 8 по 15 порт
+
+
+
+
+
+int fd;
+unsigned int  utv;
+int l=1;
+int x=0;
+
+// Open a connection to the mcp
+// Returns a file id
+int mcp_i2c_Begin()
+{
+   char *fileName = "/dev/i2c-7"; // указать Ваш адрес
+   
+   // Open port for reading and writing
+   if ((fd = open(fileName, O_RDWR)) < 0){
+     printf("i2c device not found \n");
+      exit(1);
+   } 
+   // Set the port options and set the address of the device
+   if (ioctl(fd, I2C_SLAVE, mcp_I2C_ADDRESS) < 0) {               
+      close(fd);
+      printf("on i2c mcp device not found \n");
+      exit(1);
+   }
+
+   return fd;
+}
+
+// Read a byte to mcp
+__s32 mcp_i2c_Read_byte(int fd, __u8 address)
+{
+   __s32 res = i2c_smbus_read_byte_data(fd, address);
+   if (res < 0) {
+      printf("error \n");
+      close(fd);
+      exit(1);
+   }
+
+   return res;
+}
+
+//Write a byte to mcp
+void mcp_i2c_Write_Byte(int fd, __u8 address, __u8 value)
+{
+   if (i2c_smbus_write_byte_data(fd, address, value) < 0) {
+      close(fd);
+      exit(1);
+   }
+}
+// чтение состояния порта
+int mcp_read (int mcppin)
+{
+ if (mcppin < 0 || mcppin >15) {
+       printf("Please select a valid GPIO pin \n");
+        exit(1);
+ }
+
+ int fd =  mcp_i2c_Begin();
+ int regbank;
+
+if (mcppin < 8){
+  
+ mcp_i2c_Write_Byte(fd,0x00,mcp_bank_a);
+ mcp_i2c_Write_Byte(fd,0x0c,gppu_bank_a);
+    regbank=0x12;
+
+//printf("bank A\n");
+} else {
+  
+    mcp_i2c_Write_Byte(fd,0x01,mcp_bank_b);
+    mcp_i2c_Write_Byte(fd,0x0d,gppu_bank_b);
+      
+   regbank=0x13;
+   mcppin=mcppin-8;
+
+ //  printf("bank B\n");
+}
+
+    utv = mcp_i2c_Read_byte(fd,regbank);
+
+      while(x <  mcppin)
+    {
+      x = x+ 1;
+      l=l*2;
+}
+
+
+if (utv & l) return 1;
+else return 0;
+
+close(fd);
+
+}
+
+
+// запрос таблицы статусов портов
+void mcp_state_in () {   
+      int fd =  mcp_i2c_Begin();
+     utv = mcp_i2c_Read_byte(fd,0x12);
+ //    printf ("--%d--\n",utv);
+             while(x <  8)
+    {
+      
+ if ((mcp_bank_a & l)) {
+      if ((utv & l)) printf ("%d 1\n",x);
+     else printf ("%d 0\n",x);
+
+} else printf ("%d -\n",x);
+      l=l*2;
+     x = x+ 1;
+     
+}
+
+      x=0;
+      l=1;
+
+          utv = mcp_i2c_Read_byte(fd,0x13);
+//           printf ("--%d--\n",utv);
+             while(x <  8)
+    {
+       if ((mcp_bank_b & l)) {
+      if ((utv & l)) printf ("%d 1\n",x+8);
+     else printf ("%d 0\n",x+8);
+
+     } else printf ("%d -\n",x+8);
+           l=l*2;
+     x = x+ 1;
+}
+             
+close(fd);
+
+}
+// установка состояния порта
+void mcp_write (int mcppin,int mcpst)
+{
+ if (mcppin < 0 || mcppin >15) {
+       printf("Please select a valid GPIO pin \n");
+        exit(1);
+ }
+   if (mcpst != 0 && mcpst != 1) {
+      printf("Не верно задан статус порта 0 или 1\n");
+        exit(1);
+ }
+  
+ int fd =  mcp_i2c_Begin();
+ int regbank;
+
+if (mcppin < 8){
+  
+ mcp_i2c_Write_Byte(fd,0x00,mcp_bank_a);
+ mcp_i2c_Write_Byte(fd,0x0c,gppu_bank_a);
+    regbank=0x14;
+
+//printf("bank A\n");
+} else {
+  
+    mcp_i2c_Write_Byte(fd,0x01,mcp_bank_b);
+    mcp_i2c_Write_Byte(fd,0x0d,gppu_bank_b);
+      
+   regbank=0x15;
+   mcppin=mcppin-8;
+
+ //  printf("bank B\n");
+}
+
+    utv = mcp_i2c_Read_byte(fd,regbank);
+
+      while(x <  mcppin)
+    {
+      x = x+ 1;
+      l=l*2;
+}
+
+
+if (!(utv & l) && mcpst==1) mcp_i2c_Write_Byte(fd,regbank,utv+l);
+if (utv & l && mcpst==0) mcp_i2c_Write_Byte(fd,regbank,utv-l);
+
+close(fd);
+
+}
+
+
+// запрос таблицы статусов портов
+void mcp_state_out () {   
+      int fd =  mcp_i2c_Begin();
+     utv = mcp_i2c_Read_byte(fd,0x14);
+ //    printf ("--%d--\n",utv);
+             while(x <  8)
+    {
+      
+ if (!(mcp_bank_a & l)) {
+      if ((utv & l)) printf ("%d 1\n",x);
+     else printf ("%d 0\n",x);
+
+} else printf ("%d -\n",x);
+      l=l*2;
+     x = x+ 1;
+     
+}
+
+      x=0;
+      l=1;
+
+          utv = mcp_i2c_Read_byte(fd,0x15);
+//           printf ("--%d--\n",utv);
+             while(x <  8)
+    {
+       if (!(mcp_bank_b & l)) {
+      if ((utv & l)) printf ("%d 1\n",x+8);
+     else printf ("%d 0\n",x+8);
+
+     } else printf ("%d -\n",x+8);
+           l=l*2;
+     x = x+ 1;
+}
+             
+close(fd);
+
+}
+// основное тело программы
+
+int main(int argc, char **argv)
+
+{
+   if (argc == 1) {
+     printf("%s <команда>\nin -чтение данных из порта,установленых на ввод\nout-установка состояния порта,установленного на вывод.\n", argv[0]);
+     return 1;
+   } 
+   else if (argc == 2) {
+  if(strcmp(argv[1], "out") == 0) mcp_state_out();
+  else if(strcmp(argv[1], "in") == 0) mcp_state_in();
+  else printf("Нет такой команды\n");
+  return 1;
+   }
+   
+   if(strcmp(argv[1], "out") == 0) {
+   
+        if (argc != 4) {
+             printf("Настройка порта: %s <порт> <состояние>\n", argv[0]);
+
+return 1;
+}
+int mcppin = atoi(argv[2]);
+int mcpst = atoi(argv[3]);
+
+mcp_write (mcppin,mcpst);
+     
+     
+   }
+   else if(strcmp(argv[1], "in")== 0) {
+   if (argc != 3) {
+             printf("Чтение одного порта: %s <порт>\n", argv[0]);
+     mcp_state_in();
+     return 1;
+   }
+   int mcppin = atoi(argv[2]);
+
+   printf ("%d\n",mcp_read (mcppin));
+   
+   }
+
+
+
+
+
+   return 0;
+}
\ No newline at end of file
diff --git a/pcf8574_1.c b/pcf8574_1.c
new file mode 100644 (file)
index 0000000..f2b8236
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+PCF8574_addr_byteout_slug.c
+----------------------
+Send address and byte to switch lines on 8 line port of i2c bus PCF8574
+-----------------------------------------------------------------------
+
+1) send the i2c address
+2) send byte to set the 8 port lines on or off
+
+usage :- type with spaces but without the < >
+<PCF8574_addr_byteout_slug> <decimal address> <decimal byte out 0-255>
+
+Home Page - http://www.sunspot.co.uk/Projects/SWEEX/slug/i2c/slug_i2c.html
+
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#define I2C_SLAVE0x0703/* Change slave address*/
+
+int i2c;
+char filename[20];
+unsigned long address;
+
+int rc;
+unsigned char data[1];
+int main(int argc, char *argv[]) 
+{
+if (argc != 3) { /* error if we are not getting just 2 inputs after the program name */
+fprintf(stderr, "usage: %s <address> <databyte>\n",argv[0]);
+exit(1);
+}
+
+/* address is the first number after the program name */
+address = atoi(argv[1]);
+/* the byte to send out to the PC8574 is the second number
+place it into the first element of the buf array */
+data[0] = atoi(argv[2]);
+
+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);
+return(0);
+}
+
diff --git a/pcf8574_2.c b/pcf8574_2.c
new file mode 100644 (file)
index 0000000..04af8c3
--- /dev/null
@@ -0,0 +1,56 @@
+/* 
+PCF8574_addr_read_slug.c
+-------------------
+read the data on the 8 line port of an i2c bus PCF8574
+------------------------------------------------------
+
+1) set the i2c address of the PCF8574
+2) send data 255 to turn off all 8 lines - make them inputs
+3) read the data on the 8 port lines as a byte
+usage :- type (without the < >)
+<PCF8574_address_read_4> <space> <i2c_bus_address_of_PCF8574_as_decimal>
+
+Home Page - http://www.sunspot.co.uk/Projects/SWEEX/slug/i2c/slug_i2c.html
+
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#define I2C_SLAVE0x0703/* Change slave address*/
+
+int i2c;
+char filename[20];
+unsigned long address;
+int rc;
+unsigned char data[1];
+int byte; /* the 8 bit byte that represents the data present on the 8 wire port */
+
+int main(int argc, char ** argv) 
+{
+if (argc != 2) { /* error if we are not getting just 1 input after the program name */
+fprintf(stderr, "usage: %s <address> <databyte>\n",argv[0]);
+exit(1);
+}
+
+/* address is the first number after the program name */
+address = atoi(argv[1]);
+
+i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */
+rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */
+
+data[0] = 255; 
+write(i2c,data,1); /* we send 255 to make all lines go off, ready for input data */
+
+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); 
+/* BYTE value is 0-256)*/
+i2c = close(i2c);
+return(0);
+}
diff --git a/pcf8574_3.c b/pcf8574_3.c
new file mode 100644 (file)
index 0000000..1ea2493
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+    PCF8574_addr_byteout.c
+    ----------------------
+    Send address and byte to switch lines on 8 line port of i2c bus PCF8574
+    -----------------------------------------------------------------------
+
+      1) send the i2c address
+      2) send byte to set the 8 port lines on or off
+
+  usage :-  type with spaces but without the < >
+<PCF8574_addr_byteout.c>  <address as decimal> <byte out value as decimal 0-255>
+
+*/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/i2c.h>
+
+  int i2c;
+  int buf[1];
+  int address;
+
+int main(int argc, char** argv)
+{
+ if (argc != 3)   /* error if we are not getting just 2 inputs after the program name */
+ {
+  printf("Error. usage: %s i2c_chip_address byte_to_send_out\n", argv[0]);           
+ }
+
+/* address is the first number after the program name */
+       address = atoi(argv[1]);
+
+/* the byte to send out to the PC8574 is the second number */
+
+/* place it into the first element of the buf array */
+       buf[0] = atoi(argv[2]);
+
+  i2c = open("/dev/i2c/0",O_RDWR); /* open the device on i2c-bus number 0*/
+
+  ioctl(i2c,I2C_SLAVE, address); /* set the i2c chip address */
+
+  write(i2c,buf,1); /* send the byte */
+
+  i2c = close(i2c);
+
+}
+
diff --git a/pcf8574_4.c b/pcf8574_4.c
new file mode 100644 (file)
index 0000000..d07add9
--- /dev/null
@@ -0,0 +1,50 @@
+/*
+    PCF8574_addr_read.c
+    -------------------
+read the data on the 8 line port of an i2c bus PCF8574
+------------------------------------------------------
+
+1) set the i2c address of the PCF8574
+2) send data 255 to turn off all 8 lines - make them inputs
+3) read the data on the 8 port lines as a byte
+  usage :- type (without the < >)
+  <PCF8574_address_read_4> <space> <i2c_bus_address_of_PCF8574_as_decimal>
+*/
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <linux/i2c.h>
+
+  int i2c;
+  int buf[1];
+  int address; /* i2c bus address of the PCF8574 */
+  int byte;    /* the 8 bit byte that represents the data present on the 8 wire port */
+
+int main(int argc, char** argv)
+{
+ if (argc != 2)   /* report error if we are not getting just 1 input after the program name */
+ {
+  printf("Error. usage: %s i2c_chip_address\n", argv[0]);
+ }
+
+  address = atoi(argv[1]); /* address is the first number after the program name */
+
+  i2c = open("/dev/i2c/0",O_RDWR); /* open the i2c-bus number 0 */
+
+  ioctl(i2c,I2C_SLAVE, address); /* set the address of the chip we will talk to */
+
+  buf[0] = 255; 
+  write(i2c,buf,1); /* we send 255 to make all lines go off, ready for input data */
+
+  read(i2c,buf,1); /* now buf(0) contains the byte of data on the 8 port lines*/
+
+  byte = buf[0];
+
+  printf("BYTE = %d \n", byte); 
+/* BYTE value is 0-256)*/
+
+  i2c = close(i2c);
+}
+
diff --git a/pcf8591_1.c b/pcf8591_1.c
new file mode 100644 (file)
index 0000000..17954ea
--- /dev/null
@@ -0,0 +1,95 @@
+/* 
+PCF8591-all-lines_addr_V-slug.c
+---------------------
+read the voltage on all A/D lines (0-3) and set the output voltage on the D/A pin
+---------------------------------------------------------------------------------
+
+1) send the i2c address
+3) send byte for D/A out
+3) read all 4 A/D lines
+usage :- type with spaces but without the < >
+<PCF8591_address_readvolts> <address as decimal> <D/A value as decimal 0-255>
+(even if the D/A pin is unused type in any value 0-255)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#define I2C_SLAVE0x0703/* Change slave address*/
+int i2c; 
+int AD_line; /* line number 0-3 */
+int V_out; /* value for the D/A out line */
+unsigned char buf[1]; /* use to feed the i2c driver */
+unsigned long address; /* i2c bus address */
+int byte_in_0; /* the 8 bit byte that represents the voltage on the AD_line */
+int AD_line_0; /* volts byte on line number 0 */
+int AD_line_1; /* volts byte on line number 1 */
+int AD_line_2; /* volts byte on line number 2 */
+int AD_line_3; /* volts byte on line number 3 */
+int rc;
+
+int main(int argc, char** argv)
+{
+if (argc != 3) /* report error if we are not getting just 2 inputs after the program name */
+
+{
+
+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 */
+rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */
+
+AD_line = 0 + 64; /* enable the D/A output pin 0*/
+buf[0] = AD_line; /* A/D input line number is the first data byte sent */
+buf[1] = V_out; /* D/A out value is the second data byte sent */
+write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
+read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */
+sleep (1);     /* do it again */
+read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/
+AD_line_0 = buf[0];
+
+AD_line = 1 + 64; /* enable the D/A output pin 0*/
+buf[0] = AD_line; /* A/D input line number is the first data byte sent */
+buf[1] = V_out; /* D/A out value is the second data byte sent */
+write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
+read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */
+//sleep (1);   /* do it again */
+// read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/
+AD_line_1 = buf[0];
+
+AD_line = 2 + 64; /* enable the D/A output pin 0*/
+buf[0] = AD_line; /* A/D input line number is the first data byte sent */
+buf[1] = V_out; /* D/A out value is the second data byte sent */
+write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
+read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */
+//sleep (1);   /* do it again */
+// read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/
+AD_line_2 = buf[0];
+
+AD_line = 3 + 64; /* enable the D/A output pin 0*/
+buf[0] = AD_line; /* A/D input line number is the first data byte sent */
+buf[1] = V_out; /* D/A out value is the second data byte sent */
+write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
+read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */
+//sleep (1);   /* do it again */
+// read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/
+AD_line_3 = buf[0];
+
+printf("A/D line 0 = %d \n", AD_line_0, " "); 
+printf("A/D line 1 = %d \n", AD_line_1, " ");
+printf("A/D line 2 = %d \n", AD_line_2, " ");
+printf("A/D line 3 = %d \n", AD_line_3, " ");
+/*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/
+
+i2c = close(i2c);
+return(0);
+}
diff --git a/pcf8591_2.c b/pcf8591_2.c
new file mode 100644 (file)
index 0000000..cbbc2ed
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+    PCF8591_addr_line.c
+    -------------------
+    read the voltage on one A/D line (0-3) and set the output voltage on the D/A pin
+    --------------------------------------------------------------------------------
+
+      1) send the i2c address as decimal
+      2) send A/D line number (program adds 64 to enable D/A in control register)
+      3) send byte for D/A out
+      4) read the chosen A/D - print it as a raw decimal 0 to 255
+      5) save the chosen port value to /var/www/ramdisk/AtoD.dat
+  usage :-  type with spaces but without the < >
+<PCF8591_address_readvolts>  <address as decimal> <A/D line 0-3> <D/A value as decimal 0-255>
+      (even if the D/A pin is unused type in any value 0-255)
+*/
+
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+#include "smbus.h"
+
+
+int main(int argc, char** argv)
+{
+  int i2c; 
+  int AD_line;      /* line number 0-3 */
+  int V_out;        /* value for the D/A out line */
+  int buf[1];       /* use to feed the i2c driver */
+  int address;      /* i2c bus address */
+  int byte_in_0;    /* the 8 bit byte that represents the voltage on the AD_line */
+
+ if (argc != 4)   /* report error if we are not getting just 3 inputs after the program name */
+ {
+  printf("Error. usage: %s i2c_chip_address A/D_line_(0-3) D/A_Vout(0-255)\n", argv[0]);
+ }
+
+  address = atoi(argv[1]); /* address is the first number after the program name */
+  AD_line = atoi(argv[2]); /* A/D input line 0-3 */
+  AD_line = AD_line + 64;  /* enable the D/A output pin */
+  V_out = atoi(argv[3]); /* A/D input line 0-3 */
+
+  i2c = open("/dev/i2c/0",O_RDWR); /* open the i2c-bus number 0 */
+
+  ioctl(i2c,I2C_SLAVE, address); /* set the i2c-bus address of the chip we will talk to */
+
+  buf[0] = AD_line;       /* A/D input line number is the first data byte sent */
+  buf[1] = V_out;         /* D/A out value is the second data byte sent */
+
+  write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
+
+  read(i2c,buf,1);  /* buf(0) contains the byte of data in the chip cache */
+  /* do it again */
+  read(i2c,buf,1);  /* buf(0) now contains the byte of data from the most recent analogue input*/
+
+  printf("BYTE = %d \n", buf[0]);
+  printf("%d\n", buf[0]);
+  /* buf[0] is an integer. It goes 0 to 255 as voltage input goes from 0 to supply voltage*/
+
+  //save AtoD byte to ramdisk
+  FILE *f;
+  f = fopen("/tmp/AtoD.dat","w");
+  fprintf(f, "%d", buf[0]);
+  fclose(f);
+
+  i2c = close(i2c);
+}
+
+
diff --git a/pcf8591_3.c b/pcf8591_3.c
new file mode 100644 (file)
index 0000000..acb0e4a
--- /dev/null
@@ -0,0 +1,66 @@
+/* 
+PCF8591_address_channel_Vout.c
+------------------------------
+read the voltage on one A/D lines (0-3) and set the output voltage on the D/A pin
+---------------------------------------------------------------------------------
+
+1) send the i2c address
+2) choose channel 0-3
+3) send byte for D/A out
+3) read channel volts as (0 to 255) / 255 x 5V
+usage :- type with spaces but without the < >
+<PCF8591_address_readvolts> <address as decimal> <channel 0-3> <D/A value as decimal 0-255>
+(even if the D/A pin is unused type in any value 0-255)
+*/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#define I2C_SLAVE0x0703/* Change slave address*/
+int i2c; 
+int channel; /* line number 0-3 */
+int V_out; /* value for the D/A out line */
+unsigned char buf[1]; /* use to feed the i2c driver */
+unsigned long address; /* i2c bus address */
+int byte_in_0; /* the 8 bit byte that represents the voltage on the AD_line */
+int AD_input; /* volts byte on chosen channel */
+
+int rc;
+
+int main(int argc, char** argv)
+{
+if (argc != 4) /* report error if we are not getting just 3 inputs after the program name */
+{
+printf("Error. usage: %s i2c_chip_address channel_to_read D/A_Vout(0-255)\n", argv[0]); 
+}
+
+address = atoi(argv[1]); /* decimal address is the first number after the program name */
+channel = atoi(argv[2]); /* choose A to D line to read 0-3 */
+V_out = atoi(argv[3]); /* volts out as decimal 0-255 */
+
+i2c = open("/dev/i2c-0",O_RDWR); /* open the device dev/i2c-0 */
+rc=ioctl(i2c,I2C_SLAVE,address); /* set the i2c chip address */
+
+channel = channel + 64; /* enable the D/A output */
+buf[0] = channel; /* A/D input line number is the first data byte sent */
+buf[1] = V_out; /* D/A out value is the second data byte sent */
+write(i2c,buf,2); /* we send 2 bytes <control register> <D/A value> */
+read(i2c,buf,1); /* buf(0) contains the byte of data in the chip cache */
+usleep (1000); /* do it again */
+read(i2c,buf,1); /* buf(0) now contains the byte of data from the most recent analogue input*/
+AD_input = buf[0];
+
+
+printf("%d", AD_input);
+
+
+/*AD_line_x goes 0 to 255 as voltage input goes from 0 to supply voltage*/
+
+i2c = close(i2c);
+return(0);
+}
diff --git a/pcf8591_4.c b/pcf8591_4.c
new file mode 100644 (file)
index 0000000..0a40ad6
--- /dev/null
@@ -0,0 +1,112 @@
+#include <stdio.h>
+#include <stdint.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+#include <sys/ioctl.h>
+#include "smbus.h"
+#include <ncurses.h> /* sudo apt-get install libncurses5-dev */
+
+// gcc -o pcf8591_2 -lncurses pcf8591_2.c
+
+int main( int argc, char **argv )
+{
+   int i;
+   int r;
+   int fd;
+   int aout;
+   unsigned char command[2];
+   unsigned char value[4];
+   unsigned char str[8];
+   useconds_t delay = 5000;
+
+   char *dev = "/dev/i2c-0";
+   int addr = 0x48;
+
+   int j;
+   int key;
+
+   initscr();
+   noecho();
+   cbreak();
+   nodelay(stdscr, true);
+   curs_set(0);
+   printw("PCF8591");
+
+   mvaddstr(10, 0, "Brightness");
+   mvaddstr(12, 0, "Temperature");
+   mvaddstr(14, 0, "?");
+   mvaddstr(16, 0, "Resistor");
+   refresh();
+   fd = open(dev, O_RDWR );
+   if(fd < 0)
+   {
+      perror("Opening i2c device node\n");
+      return 1;
+   }
+
+   r = ioctl(fd, I2C_SLAVE, addr);
+   if(r < 0)
+   {
+      perror("Selecting i2c device\n");
+   }
+
+   command[1] = 0;
+   aout = 0;
+   while(1)
+   {
+      for(i = 0; i < 4; i++)
+      {
+         command[1]=aout++;
+         command[0] = 0x40 | ((i + 1) & 0x03); // output enable | read input i
+         r = write(fd, &command, 2);
+         usleep(delay);
+         // the read is always one step behind the selected input
+         r = read(fd, &value[i], 1);
+         if(r != 1)
+         {
+            perror("reading i2c device\n");
+         }
+         usleep(delay);
+
+         sprintf(str, "%3d", value[i]);
+         mvaddstr(10+i+i, 12, str);
+         value[i] = value[i] / 4;
+         move(10 + i + i, 16);
+
+         for(j = 0; j < 64; j++)
+         {
+            if(j < value[i])
+            {
+               addch('*');
+            }
+            else
+            {
+               addch(' ');
+            }
+         }
+      }
+      refresh();
+
+      key = getch();
+      if(key == 43)
+      {
+         command[1]++;
+      }
+      else if(key == 45)
+      {
+         command[1]--;
+      }
+      else if(key > -1)
+      {
+         break;
+      }
+   }
+
+   endwin();
+   close(fd);
+   printf("%d\n", key);
+   return(0);
+}
\ No newline at end of file
diff --git a/pcf8591d.c b/pcf8591d.c
new file mode 100644 (file)
index 0000000..3613538
--- /dev/null
@@ -0,0 +1,67 @@
+//***************************************************
+// pcf8591d.c
+// 
+// Example to read A/D values from a 
+// 4 channel / 8 bit AD converter PCF8591
+// through I2C using the I2C driver improved by
+// Geert Vancompernolle
+// http://www.acmesystems.it/?id=10
+//***************************************************
+
+#include "stdio.h"
+#include "stdlib.h"
+#include "unistd.h"
+#include "sys/ioctl.h"
+#include "fcntl.h"
+#include "time.h"
+#include "string.h"
+
+#include "i2c_errno.h"
+#include "etraxi2c.h"
+
+
+int main( int argc, char **argv ) {
+  int rtc;
+  int fd_i2c;
+  I2C_DATA i2c_d;
+  int ch;
+
+  printf("Reading from a PCF8591 (4 chanel A/D at 8 bits with I2C bus)\n");
+
+  fd_i2c = open( "/dev/i2c-0", O_RDWR );
+  if (fd_i2c<=0)     {
+    printf( "Open error on /dev/i2c\n" );
+    exit( 1 );
+  }
+
+  // PCF8591 address scheme
+  // |  1 |  0 |  0 |  1 | A2 | A1 | A0 | R/W |
+//  i2c_d.slave =(0x09<<4)|(0x01<<1);
+
+  i2c_d.slave = 0x48;
+
+  for (ch=0;ch<=3;ch++) {
+    // Select the A/D channel
+    i2c_d.wbuf[0] = ch;
+    i2c_d.wlen  = 1;
+    if ((rtc=ioctl(fd_i2c,_IO( ETRAXI2C_IOCTYPE, I2C_WRITE), &i2c_d))!=EI2CNOERRORS)  {
+      close(fd_i2c);
+      printf( "Error %d on line %d\n",rtc,__LINE__);
+      return ( -1 );
+    }
+
+    i2c_d.rlen  = 3;
+    if ((rtc=ioctl(fd_i2c,_IO( ETRAXI2C_IOCTYPE, I2C_READ), &i2c_d))!=EI2CNOERRORS)  {
+      close(fd_i2c);
+      printf( "Error %d on line %d\n",rtc,__LINE__);
+      return ( -1 );
+    }
+
+    // Show the voltage level
+    printf("Chanel %d = %.2fv (%02X hex)\n",ch,i2c_d.rbuf[2]*0.012941,i2c_d.rbuf[2]);
+  }
+
+  close(fd_i2c);
+  return(0);
+}
+
diff --git a/sethwclock b/sethwclock
new file mode 100644 (file)
index 0000000..40e94d7
--- /dev/null
@@ -0,0 +1,26 @@
+#!/bin/sh
+
+I2CBUS=0
+I2CADDR=0x68
+
+if [ "$1" == "" ]
+then
+  date=`date -u +%Y%m%d%H%M%S`
+else
+  date=$1
+fi
+
+year=${date:2:2}
+month=${date:4:2}
+day=${date:6:2}
+
+hour=${date:8:2}
+min=${date:10:2}
+sec=${date:12:2}
+
+i2cset -y $I2CBUS $I2CADDR 0 0x$sec
+i2cset -y $I2CBUS $I2CADDR 1 0x$min
+i2cset -y $I2CBUS $I2CADDR 2 0x$hour
+i2cset -y $I2CBUS $I2CADDR 4 0x$day
+i2cset -y $I2CBUS $I2CADDR 5 0x$month
+i2cset -y $I2CBUS $I2CADDR 6 0x$year
diff --git a/sht21.c b/sht21.c
new file mode 100644 (file)
index 0000000..4a415a6
--- /dev/null
+++ b/sht21.c
@@ -0,0 +1,110 @@
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/i2c-dev.h>
+#include <linux/i2c.h>
+
+#include <unistd.h>             /* add by paulerr*/
+
+
+#define CHIP                   "/dev/i2c-0"
+#define CHIP_ADDR              0x40                    //HTU21D地址
+#define READ_TEMP              0XE3                    //温度转换命令
+#define READ_HUM               0XE5                    //湿度转换命令
+
+/* More info: https://github.com/kingmacth/Openwet-SDK/tree/master/package/HTU21D  */
+
+unsigned char HTU21D_Check_CRC(unsigned short int message_from_sensor,unsigned char check_value_from_sensor);
+
+int main()
+
+{
+         printf("hello,this is HTU21D tester \n");
+         int fd =open(CHIP, O_RDWR);
+         if (fd< 0) {
+                   printf("open"CHIP"failed \n");
+                   goto exit;
+         }
+
+         if (ioctl(fd,I2C_SLAVE_FORCE, CHIP_ADDR) < 0) {           /*设置芯片地址   */
+                   printf("oictl:setslave address failed\n");
+                   goto close;
+         }
+
+       struct          i2c_msg msg;
+
+       unsigned char      rddata[3];
+       unsigned char      rdaddr[2] = {0x10, 0};     /* 将要读取的数据在芯片中的偏移量  */
+       unsigned char      TempAddr[2] = {0xe3, 0};   /* 发送E3读取温度    */
+       unsigned char      HumAddr[2] = {0xE5, 0};    /* 发送E5读取湿度    */
+       unsigned short int tmp_dat,CRC_Result;
+       float Temp,Hum;
+         /*printf("inputa char you want to write to E2PROM\n");
+         wrbuf[2]= getchar();
+         printf("writereturn:%d, write data:%x\n", write(fd, wrbuf, 1), wrbuf[2]);
+         sleep(5);*/
+         //printf("Read temp!\n",write(fd, TempAddr, 1));      /* 开启温度转换    */
+       write(fd, TempAddr, 1);
+        usleep(100000);
+         read(fd, &rddata, 3);         //读取两字节温度一字节校验
+         
+       tmp_dat=rddata[0];
+       tmp_dat=tmp_dat<<8;
+       tmp_dat=tmp_dat+rddata[1];
+       //printf("rddata:%x%02x,%x\n", rddata[0], rddata[1],rddata[2]);
+       CRC_Result=HTU21D_Check_CRC(tmp_dat,rddata[2]);
+       //printf("CRC=%x,%x\n",CRC_Result ,tmp_dat);//CRC校验
+       if(CRC_Result==0)
+       {
+               Temp=(tmp_dat*175.72)/65536-46.85;
+               printf("Temp=%.2f\n",Temp);
+       }
+        //printf("Read hum!\n",write(fd, HumAddr, 1));      /* 开启湿度转换    */
+       write(fd, HumAddr, 1);
+        usleep(100000);
+         read(fd, &rddata, 3);         //读取两字节湿度一字节校验
+         
+       tmp_dat=rddata[0];
+       tmp_dat=tmp_dat<<8;
+       tmp_dat=tmp_dat+rddata[1];
+       //printf("rddata:%x%02x,%x\n", rddata[0], rddata[1],rddata[2]);
+       CRC_Result=HTU21D_Check_CRC(tmp_dat,rddata[2]);
+       //printf("CRC=%x,%x\n",CRC_Result ,tmp_dat);//CRC校验
+       if(CRC_Result==0)
+       {
+               Temp=(tmp_dat*125)/65536-6;
+               printf("Hum=%.2f%%RH\n",Temp);
+       }
+
+close:
+         close(fd);
+exit:
+         return 0;
+
+}
+
+//**************************************************************************************************************
+//两个参数一个是传感器的源数据,另一个是传感器得出的CRC校验值
+//如果校验通过返回0,不通过返回非0
+//From: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html
+//POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 : http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
+#define SHIFTED_DIVISOR 0x988000 //This is the 0x0131 polynomial shifted to farthest left of three bytes
+//**************************************************************************************************************
+unsigned char HTU21D_Check_CRC(unsigned short int message_from_sensor,unsigned char check_value_from_sensor)
+{
+unsigned char i;
+//Test cases from datasheet:
+//message = 0xDC, checkvalue is 0x79
+//message = 0x683A, checkvalue is 0x7C
+//message = 0x4E85, checkvalue is 0x6B
+unsigned int remainder = (unsigned int)message_from_sensor << 8; //Pad with 8 bits because we have to add in the check value
+unsigned int divsor = (unsigned int)SHIFTED_DIVISOR;
+remainder |= check_value_from_sensor; //Add on the check value
+for (i = 0 ; i < 16 ; i++) //Operate on only 16 positions of max 24. The remaining 8 are our remainder and should be zero when we're done.
+{
+if( remainder & (unsigned int)1<<(23 - i) ) //Check if there is a one in the left position
+remainder ^= divsor;
+divsor>>=1;//Rotatethedivsormax16timessothatwehave8bitsleftofaremainder
+}
+return(unsigned char)remainder;
+}
diff --git a/smbus.c b/smbus.c
new file mode 100644 (file)
index 0000000..623519e
--- /dev/null
+++ b/smbus.c
@@ -0,0 +1,228 @@
+/*
+    smbus.c - SMBus level access helper functions
+
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+    Copyright (C) 2012    Jean Delvare <khali@linux-fr.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
+*/
+
+#include <errno.h>
+#include "smbus.h"     // NB: Path changed!
+#include <sys/ioctl.h>
+#include <linux/types.h>
+#include <linux/i2c.h>
+#include <linux/i2c-dev.h>
+
+//NB: Added by John Burns
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* Compatibility defines */
+#ifndef I2C_SMBUS_I2C_BLOCK_BROKEN
+#define I2C_SMBUS_I2C_BLOCK_BROKEN I2C_SMBUS_I2C_BLOCK_DATA
+#endif
+#ifndef I2C_FUNC_SMBUS_PEC
+#define I2C_FUNC_SMBUS_PEC I2C_FUNC_SMBUS_HWPEC_CALC
+#endif
+
+__s32 i2c_smbus_access(int file, char read_write, __u8 command,
+                      int size, union i2c_smbus_data *data)
+{
+       struct i2c_smbus_ioctl_data args;
+       __s32 err;
+
+       args.read_write = read_write;
+       args.command = command;
+       args.size = size;
+       args.data = data;
+
+       err = ioctl(file, I2C_SMBUS, &args);
+       if (err == -1)
+               err = -errno;
+       return err;
+}
+
+
+__s32 i2c_smbus_write_quick(int file, __u8 value)
+{
+       return i2c_smbus_access(file, value, 0, I2C_SMBUS_QUICK, NULL);
+}
+
+__s32 i2c_smbus_read_byte(int file)
+{
+       union i2c_smbus_data data;
+       int err;
+
+       err = i2c_smbus_access(file, I2C_SMBUS_READ, 0, I2C_SMBUS_BYTE, &data);
+       if (err < 0)
+               return err;
+
+       return 0x0FF & data.byte;
+}
+
+__s32 i2c_smbus_write_byte(int file, __u8 value)
+{
+       return i2c_smbus_access(file, I2C_SMBUS_WRITE, value,
+                               I2C_SMBUS_BYTE, NULL);
+}
+
+__s32 i2c_smbus_read_byte_data(int file, __u8 command)
+{
+       union i2c_smbus_data data;
+       int err;
+
+       err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
+                              I2C_SMBUS_BYTE_DATA, &data);
+       if (err < 0)
+               return err;
+
+       return 0x0FF & data.byte;
+}
+
+__s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value)
+{
+       union i2c_smbus_data data;
+       data.byte = value;
+       return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_BYTE_DATA, &data);
+}
+
+__s32 i2c_smbus_read_word_data(int file, __u8 command)
+{
+       union i2c_smbus_data data;
+       int err;
+
+       err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
+                              I2C_SMBUS_WORD_DATA, &data);
+       if (err < 0)
+               return err;
+
+       return 0x0FFFF & data.word;
+}
+
+__s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value)
+{
+       union i2c_smbus_data data;
+       data.word = value;
+       return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_WORD_DATA, &data);
+}
+
+__s32 i2c_smbus_process_call(int file, __u8 command, __u16 value)
+{
+       union i2c_smbus_data data;
+       data.word = value;
+       if (i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+                            I2C_SMBUS_PROC_CALL, &data))
+               return -1;
+       else
+               return 0x0FFFF & data.word;
+}
+
+/* Returns the number of read bytes */
+__s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values)
+{
+       union i2c_smbus_data data;
+       int i, err;
+
+       err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
+                              I2C_SMBUS_BLOCK_DATA, &data);
+       if (err < 0)
+               return err;
+
+       for (i = 1; i <= data.block[0]; i++)
+               values[i-1] = data.block[i];
+       return data.block[0];
+}
+
+__s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
+                                const __u8 *values)
+{
+       union i2c_smbus_data data;
+       int i;
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       for (i = 1; i <= length; i++)
+               data.block[i] = values[i-1];
+       data.block[0] = length;
+       return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_BLOCK_DATA, &data);
+}
+
+/* Returns the number of read bytes */
+/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
+   ask for less than 32 bytes, your code will only work with kernels
+   2.6.23 and later. */
+__s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
+                                   __u8 *values)
+{
+       union i2c_smbus_data data;
+       int i, err;
+
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       data.block[0] = length;
+
+       err = i2c_smbus_access(file, I2C_SMBUS_READ, command,
+                              length == 32 ? I2C_SMBUS_I2C_BLOCK_BROKEN :
+                               I2C_SMBUS_I2C_BLOCK_DATA, &data);
+       if (err < 0)
+               return err;
+
+       for (i = 1; i <= data.block[0]; i++)
+               values[i-1] = data.block[i];
+       return data.block[0];
+}
+
+__s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
+                                    const __u8 *values)
+{
+       union i2c_smbus_data data;
+       int i;
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       for (i = 1; i <= length; i++)
+               data.block[i] = values[i-1];
+       data.block[0] = length;
+       return i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_I2C_BLOCK_BROKEN, &data);
+}
+
+/* Returns the number of read bytes */
+__s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
+                                  __u8 *values)
+{
+       union i2c_smbus_data data;
+       int i, err;
+
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       for (i = 1; i <= length; i++)
+               data.block[i] = values[i-1];
+       data.block[0] = length;
+
+       err = i2c_smbus_access(file, I2C_SMBUS_WRITE, command,
+                              I2C_SMBUS_BLOCK_PROC_CALL, &data);
+       if (err < 0)
+               return err;
+
+       for (i = 1; i <= data.block[0]; i++)
+               values[i-1] = data.block[i];
+       return data.block[0];
+}
diff --git a/smbus.h b/smbus.h
new file mode 100644 (file)
index 0000000..b7facf6
--- /dev/null
+++ b/smbus.h
@@ -0,0 +1,59 @@
+/*
+    smbus.h - SMBus level access helper functions
+
+    Copyright (C) 1995-97 Simon G. Vogl
+    Copyright (C) 1998-99 Frodo Looijaard <frodol@dds.nl>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+    MA 02110-1301 USA.
+*/
+
+#ifndef LIB_I2C_SMBUS_H
+#define LIB_I2C_SMBUS_H
+
+#include <linux/types.h>
+#include <linux/i2c.h>
+
+extern __s32 i2c_smbus_access(int file, char read_write, __u8 command,
+                             int size, union i2c_smbus_data *data);
+
+extern __s32 i2c_smbus_write_quick(int file, __u8 value);
+extern __s32 i2c_smbus_read_byte(int file);
+extern __s32 i2c_smbus_write_byte(int file, __u8 value);
+extern __s32 i2c_smbus_read_byte_data(int file, __u8 command);
+extern __s32 i2c_smbus_write_byte_data(int file, __u8 command, __u8 value);
+extern __s32 i2c_smbus_read_word_data(int file, __u8 command);
+extern __s32 i2c_smbus_write_word_data(int file, __u8 command, __u16 value);
+extern __s32 i2c_smbus_process_call(int file, __u8 command, __u16 value);
+
+/* Returns the number of read bytes */
+extern __s32 i2c_smbus_read_block_data(int file, __u8 command, __u8 *values);
+extern __s32 i2c_smbus_write_block_data(int file, __u8 command, __u8 length,
+                                       const __u8 *values);
+
+/* Returns the number of read bytes */
+/* Until kernel 2.6.22, the length is hardcoded to 32 bytes. If you
+   ask for less than 32 bytes, your code will only work with kernels
+   2.6.23 and later. */
+extern __s32 i2c_smbus_read_i2c_block_data(int file, __u8 command, __u8 length,
+                                          __u8 *values);
+extern __s32 i2c_smbus_write_i2c_block_data(int file, __u8 command, __u8 length,
+                                           const __u8 *values);
+
+/* Returns the number of read bytes */
+extern __s32 i2c_smbus_block_process_call(int file, __u8 command, __u8 length,
+                                         __u8 *values);
+
+#endif /* LIB_I2C_SMBUS_H */
diff --git a/syncfromhwclock b/syncfromhwclock
new file mode 100644 (file)
index 0000000..e07d3ba
--- /dev/null
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+date -u -s "`gethwclock`"