| 3331 | kaklik | 1 | /* | 
      
        |  |  | 2 |  * i2c_usb.c - test application for the i2c-tiby-usb interface | 
      
        |  |  | 3 |  *             http://www.harbaum.org/till/i2c_tiny_usb | 
      
        |  |  | 4 |  * | 
      
        |  |  | 5 |  * $Id: i2c_usb.c,v 1.5 2007/01/05 19:30:43 harbaum Exp $ | 
      
        |  |  | 6 |  */ | 
      
        |  |  | 7 |  | 
      
        |  |  | 8 | #include <stdio.h> | 
      
        |  |  | 9 | #include <stdlib.h> | 
      
        |  |  | 10 | #include <string.h> | 
      
        |  |  | 11 | #include <usb.h> | 
      
        |  |  | 12 |  | 
      
        |  |  | 13 | /* ds1621 chip address (A0-A2 tied low) */ | 
      
        |  |  | 14 | #define DS1621_ADDR  0x48 | 
      
        |  |  | 15 |  | 
      
        |  |  | 16 | /* pcf8574 chip address (A0-A2 tied low) */ | 
      
        |  |  | 17 | #define PCF8574_ADDR  0x20 | 
      
        |  |  | 18 |  | 
      
        |  |  | 19 | #define LOOPS 100 | 
      
        |  |  | 20 |  | 
      
        |  |  | 21 | #define USB_CTRL_IN    (USB_TYPE_CLASS | USB_ENDPOINT_IN) | 
      
        |  |  | 22 | #define USB_CTRL_OUT   (USB_TYPE_CLASS) | 
      
        |  |  | 23 |  | 
      
        |  |  | 24 | /* the vendor and product id was donated by ftdi ... many thanks!*/ | 
      
        |  |  | 25 | #define I2C_TINY_USB_VID  0x0403 | 
      
        |  |  | 26 | #define I2C_TINY_USB_PID  0xc631 | 
      
        |  |  | 27 |  | 
      
        |  |  | 28 | #ifdef WIN | 
      
        |  |  | 29 | #include <windows.h> | 
      
        |  |  | 30 | #include <winbase.h> | 
      
        |  |  | 31 | #define usleep(t) Sleep((t) / 1000) | 
      
        |  |  | 32 | #endif | 
      
        |  |  | 33 |  | 
      
        |  |  | 34 | #define I2C_M_RD		0x01 | 
      
        |  |  | 35 |  | 
      
        |  |  | 36 | /* commands via USB, must e.g. match command ids firmware */ | 
      
        |  |  | 37 | #define CMD_ECHO       0 | 
      
        |  |  | 38 | #define CMD_GET_FUNC   1 | 
      
        |  |  | 39 | #define CMD_SET_DELAY  2 | 
      
        |  |  | 40 | #define CMD_GET_STATUS 3 | 
      
        |  |  | 41 | #define CMD_I2C_IO     4 | 
      
        |  |  | 42 | #define CMD_I2C_BEGIN  1  // flag to I2C_IO | 
      
        |  |  | 43 | #define CMD_I2C_END    2  // flag to I2C_IO | 
      
        |  |  | 44 |  | 
      
        |  |  | 45 | #define STATUS_IDLE          0 | 
      
        |  |  | 46 | #define STATUS_ADDRESS_ACK   1 | 
      
        |  |  | 47 | #define STATUS_ADDRESS_NAK   2 | 
      
        |  |  | 48 |  | 
      
        |  |  | 49 | usb_dev_handle      *handle = NULL; | 
      
        |  |  | 50 |  | 
      
        |  |  | 51 | /* write a set of bytes to the i2c_tiny_usb device */ | 
      
        |  |  | 52 | int i2c_tiny_usb_write(int request, int value, int index){ | 
      
        |  |  | 53 |  | 
      
        |  |  | 54 |   if(usb_control_msg(handle, USB_CTRL_OUT, request,  | 
      
        |  |  | 55 | 		      value, index, NULL, 0, 1000) < 0) { | 
      
        |  |  | 56 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 57 |     return -1; | 
      
        |  |  | 58 |   } | 
      
        |  |  | 59 |   return 1; | 
      
        |  |  | 60 | } | 
      
        |  |  | 61 |  | 
      
        |  |  | 62 | /* read a set of bytes from the i2c_tiny_usb device */ | 
      
        |  |  | 63 | int i2c_tiny_usb_read(unsigned char cmd, void *data, int len) { | 
      
        |  |  | 64 |   int                 nBytes; | 
      
        |  |  | 65 |  | 
      
        |  |  | 66 |   /* send control request and accept return value */ | 
      
        |  |  | 67 |   nBytes = usb_control_msg(handle,USB_CTRL_IN, cmd, 0, 0, data, len, 1000); | 
      
        |  |  | 68 |  | 
      
        |  |  | 69 |   if(nBytes < 0) { | 
      
        |  |  | 70 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 71 |     return nBytes; | 
      
        |  |  | 72 |   } | 
      
        |  |  | 73 |  | 
      
        |  |  | 74 |   return 0; | 
      
        |  |  | 75 | } | 
      
        |  |  | 76 |  | 
      
        |  |  | 77 | /* get i2c usb interface test */ | 
      
        |  |  | 78 | void i2c_tiny_usb_test(void) { | 
      
        |  |  | 79 |   unsigned long func; | 
      
        |  |  | 80 |  | 
      
        |  |  | 81 |   if(i2c_tiny_usb_read(CMD_ECHO, &func, sizeof(func)) == 0) | 
      
        |  |  | 82 |     printf("Functionality = %lx\n", func); | 
      
        |  |  | 83 | } | 
      
        |  |  | 84 |  | 
      
        |  |  | 85 |  | 
      
        |  |  | 86 | /* get i2c usb interface firmware version */ | 
      
        |  |  | 87 | void i2c_tiny_usb_get_func(void) { | 
      
        |  |  | 88 |   unsigned long func; | 
      
        |  |  | 89 |  | 
      
        |  |  | 90 |   if(i2c_tiny_usb_read(CMD_GET_FUNC, &func, sizeof(func)) == 0) | 
      
        |  |  | 91 |     printf("Functionality = %lx\n", func); | 
      
        |  |  | 92 | } | 
      
        |  |  | 93 |  | 
      
        |  |  | 94 | /* set a value in the I2C_USB interface */ | 
      
        |  |  | 95 | void i2c_tiny_usb_set(unsigned char cmd, int value) { | 
      
        |  |  | 96 |   if(usb_control_msg(handle,  | 
      
        |  |  | 97 | 	     USB_TYPE_VENDOR, cmd, value, 0,  | 
      
        |  |  | 98 | 	     NULL, 0, 1000) < 0) { | 
      
        |  |  | 99 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 100 |   } | 
      
        |  |  | 101 | } | 
      
        |  |  | 102 |  | 
      
        |  |  | 103 | /* get the current transaction status from the i2c_tiny_usb interface */ | 
      
        |  |  | 104 | int i2c_tiny_usb_get_status(void) { | 
      
        |  |  | 105 |   int i; | 
      
        |  |  | 106 |   unsigned char status; | 
      
        |  |  | 107 |  | 
      
        |  |  | 108 |   if((i=i2c_tiny_usb_read(CMD_GET_STATUS, &status, sizeof(status))) < 0) { | 
      
        |  |  | 109 |     fprintf(stderr, "Error reading status\n"); | 
      
        |  |  | 110 |     return i; | 
      
        |  |  | 111 |   } | 
      
        |  |  | 112 |  | 
      
        |  |  | 113 |   return status; | 
      
        |  |  | 114 | } | 
      
        |  |  | 115 |  | 
      
        |  |  | 116 | /* write command and read an 8 or 16 bit value from the given chip */ | 
      
        |  |  | 117 | int i2c_read_with_cmd(unsigned char addr, char cmd, int length) { | 
      
        |  |  | 118 |   unsigned char result[2]; | 
      
        |  |  | 119 |  | 
      
        |  |  | 120 |   if((length < 0) || (length > sizeof(result))) { | 
      
        |  |  | 121 |     fprintf(stderr, "request exceeds %lu bytes\n", sizeof(result)); | 
      
        |  |  | 122 |     return -1; | 
      
        |  |  | 123 |   }  | 
      
        |  |  | 124 |  | 
      
        |  |  | 125 |   /* write one byte register address to chip */ | 
      
        |  |  | 126 |   if(usb_control_msg(handle, USB_CTRL_OUT,  | 
      
        |  |  | 127 | 		     CMD_I2C_IO + CMD_I2C_BEGIN | 
      
        |  |  | 128 | 		     + ((!length)?CMD_I2C_END:0), | 
      
        |  |  | 129 | 		     0, addr, &cmd, 1,  | 
      
        |  |  | 130 | 		     1000) < 1) { | 
      
        |  |  | 131 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 132 |     return -1; | 
      
        |  |  | 133 |   }  | 
      
        |  |  | 134 |  | 
      
        |  |  | 135 |   if(i2c_tiny_usb_get_status() != STATUS_ADDRESS_ACK) { | 
      
        |  |  | 136 |     fprintf(stderr, "write command status failed\n"); | 
      
        |  |  | 137 |     return -1; | 
      
        |  |  | 138 |   } | 
      
        |  |  | 139 |  | 
      
        |  |  | 140 |   // just a test? return ok | 
      
        |  |  | 141 |   if(!length) return 0; | 
      
        |  |  | 142 |  | 
      
        |  |  | 143 |   if(usb_control_msg(handle,  | 
      
        |  |  | 144 | 		     USB_CTRL_IN,  | 
      
        |  |  | 145 | 		     CMD_I2C_IO + CMD_I2C_END, | 
      
        |  |  | 146 | 		     I2C_M_RD, addr, (char*)result, length,  | 
      
        |  |  | 147 | 		     1000) < 1) { | 
      
        |  |  | 148 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 149 |     return -1; | 
      
        |  |  | 150 |   }  | 
      
        |  |  | 151 |  | 
      
        |  |  | 152 |   if(i2c_tiny_usb_get_status() != STATUS_ADDRESS_ACK) { | 
      
        |  |  | 153 |     fprintf(stderr, "read data status failed\n"); | 
      
        |  |  | 154 |     return -1; | 
      
        |  |  | 155 |   } | 
      
        |  |  | 156 |  | 
      
        |  |  | 157 |   // return 16 bit result | 
      
        |  |  | 158 |   if(length == 2) | 
      
        |  |  | 159 |     return 256*result[0] + result[1]; | 
      
        |  |  | 160 |  | 
      
        |  |  | 161 |   // return 8 bit result | 
      
        |  |  | 162 |   return result[0];   | 
      
        |  |  | 163 | } | 
      
        |  |  | 164 |  | 
      
        |  |  | 165 | /* write a single byte to the i2c client */ | 
      
        |  |  | 166 | int i2c_write_byte(unsigned char addr, char data) { | 
      
        |  |  | 167 |  | 
      
        |  |  | 168 |   /* write one byte register address to chip */ | 
      
        |  |  | 169 |   if(usb_control_msg(handle, USB_CTRL_OUT,  | 
      
        |  |  | 170 | 		     CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END, | 
      
        |  |  | 171 | 		     0, addr, &data, 1,  | 
      
        |  |  | 172 | 		     1000) < 1) { | 
      
        |  |  | 173 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 174 |     return -1; | 
      
        |  |  | 175 |   }  | 
      
        |  |  | 176 |  | 
      
        |  |  | 177 |   if(i2c_tiny_usb_get_status() != STATUS_ADDRESS_ACK) { | 
      
        |  |  | 178 |     fprintf(stderr, "write command status failed\n"); | 
      
        |  |  | 179 |     return -1; | 
      
        |  |  | 180 |   } | 
      
        |  |  | 181 |  | 
      
        |  |  | 182 |   return 0;   | 
      
        |  |  | 183 | } | 
      
        |  |  | 184 |  | 
      
        |  |  | 185 | /* write a command byte and a single byte to the i2c client */ | 
      
        |  |  | 186 | int i2c_write_cmd_and_byte(unsigned char addr, char cmd, char data) { | 
      
        |  |  | 187 |   char msg[2]; | 
      
        |  |  | 188 |  | 
      
        |  |  | 189 |   msg[0] = cmd; | 
      
        |  |  | 190 |   msg[1] = data; | 
      
        |  |  | 191 |  | 
      
        |  |  | 192 |   /* write one byte register address to chip */ | 
      
        |  |  | 193 |   if(usb_control_msg(handle, USB_CTRL_OUT,  | 
      
        |  |  | 194 | 		     CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END, | 
      
        |  |  | 195 | 		     0, addr, msg, 2,  | 
      
        |  |  | 196 | 		     1000) < 1) { | 
      
        |  |  | 197 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 198 |     return -1; | 
      
        |  |  | 199 |   }  | 
      
        |  |  | 200 |  | 
      
        |  |  | 201 |   if(i2c_tiny_usb_get_status() != STATUS_ADDRESS_ACK) { | 
      
        |  |  | 202 |     fprintf(stderr, "write command status failed\n"); | 
      
        |  |  | 203 |     return -1; | 
      
        |  |  | 204 |   } | 
      
        |  |  | 205 |  | 
      
        |  |  | 206 |   return 0;   | 
      
        |  |  | 207 | } | 
      
        |  |  | 208 |  | 
      
        |  |  | 209 | /* write a command byte and a 16 bit value to the i2c client */ | 
      
        |  |  | 210 | int i2c_write_cmd_and_word(unsigned char addr, char cmd, int data) { | 
      
        |  |  | 211 |   char msg[3]; | 
      
        |  |  | 212 |  | 
      
        |  |  | 213 |   msg[0] = cmd; | 
      
        |  |  | 214 |   msg[1] = data >> 8; | 
      
        |  |  | 215 |   msg[2] = data & 0xff; | 
      
        |  |  | 216 |  | 
      
        |  |  | 217 |   /* write one byte register address to chip */ | 
      
        |  |  | 218 |   if(usb_control_msg(handle, USB_CTRL_OUT,  | 
      
        |  |  | 219 | 		     CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END, | 
      
        |  |  | 220 | 		     0, addr, msg, 3,  | 
      
        |  |  | 221 | 		     1000) < 1) { | 
      
        |  |  | 222 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 223 |     return -1; | 
      
        |  |  | 224 |   }  | 
      
        |  |  | 225 |  | 
      
        |  |  | 226 |   if(i2c_tiny_usb_get_status() != STATUS_ADDRESS_ACK) { | 
      
        |  |  | 227 |     fprintf(stderr, "write command status failed\n"); | 
      
        |  |  | 228 |     return -1; | 
      
        |  |  | 229 |   } | 
      
        |  |  | 230 |  | 
      
        |  |  | 231 |   return 0;   | 
      
        |  |  | 232 | } | 
      
        |  |  | 233 |  | 
      
        |  |  | 234 | /* read ds1621 control register */ | 
      
        |  |  | 235 | void ds1621_read_control(void) { | 
      
        |  |  | 236 |   int result; | 
      
        |  |  | 237 |  | 
      
        |  |  | 238 |   do { | 
      
        |  |  | 239 |     result = i2c_read_with_cmd(DS1621_ADDR, 0xac, 1); | 
      
        |  |  | 240 |   } while(!(result & 0x80)); | 
      
        |  |  | 241 | } | 
      
        |  |  | 242 |  | 
      
        |  |  | 243 |  | 
      
        |  |  | 244 |  | 
      
        |  |  | 245 | /* main program process */  | 
      
        |  |  | 246 |  | 
      
        |  |  | 247 |  | 
      
        |  |  | 248 | int main(int argc, char *argv[]) { | 
      
        |  |  | 249 |   struct usb_bus      *bus; | 
      
        |  |  | 250 |   struct usb_device   *dev; | 
      
        |  |  | 251 |   int i; | 
      
        |  |  | 252 | #ifndef WIN | 
      
        |  |  | 253 |   int ret; | 
      
        |  |  | 254 | #endif | 
      
        |  |  | 255 |  | 
      
        |  |  | 256 |   printf("--      i2c-tiny-usb test application       --\n"); | 
      
        |  |  | 257 |   printf("--         (c) 2006 by Till Harbaum         --\n"); | 
      
        |  |  | 258 |   printf("-- http://www.harbaum.org/till/i2c_tiny_usb --\n"); | 
      
        |  |  | 259 |  | 
      
        |  |  | 260 |   usb_init(); | 
      
        |  |  | 261 |  | 
      
        |  |  | 262 |   usb_find_busses(); | 
      
        |  |  | 263 |   usb_find_devices(); | 
      
        |  |  | 264 |  | 
      
        |  |  | 265 |   for(bus = usb_get_busses(); bus; bus = bus->next) { | 
      
        |  |  | 266 |     for(dev = bus->devices; dev; dev = dev->next) { | 
      
        |  |  | 267 |       if((dev->descriptor.idVendor == I2C_TINY_USB_VID) &&  | 
      
        |  |  | 268 | 	 (dev->descriptor.idProduct == I2C_TINY_USB_PID)) { | 
      
        |  |  | 269 |  | 
      
        |  |  | 270 | 	printf("Found i2c_tiny_usb device on bus %s device %s.\n",  | 
      
        |  |  | 271 | 	       bus->dirname, dev->filename); | 
      
        |  |  | 272 |  | 
      
        |  |  | 273 | 	/* open device */ | 
      
        |  |  | 274 | 	if(!(handle = usb_open(dev)))  | 
      
        |  |  | 275 | 	  fprintf(stderr, "Error: Cannot open the device: %s\n",  | 
      
        |  |  | 276 | 		  usb_strerror()); | 
      
        |  |  | 277 |  | 
      
        |  |  | 278 | 	break; | 
      
        |  |  | 279 |       } | 
      
        |  |  | 280 |     } | 
      
        |  |  | 281 |   } | 
      
        |  |  | 282 |  | 
      
        |  |  | 283 |   if(!handle) { | 
      
        |  |  | 284 |     fprintf(stderr, "Error: Could not find i2c_tiny_usb device\n"); | 
      
        |  |  | 285 |  | 
      
        |  |  | 286 | #ifdef WIN | 
      
        |  |  | 287 |     printf("Press return to quit\n"); | 
      
        |  |  | 288 |     getchar(); | 
      
        |  |  | 289 | #endif | 
      
        |  |  | 290 |  | 
      
        |  |  | 291 |     exit(-1); | 
      
        |  |  | 292 |   } | 
      
        |  |  | 293 |  | 
      
        |  |  | 294 | #ifndef WIN | 
      
        |  |  | 295 |   /* Get exclusive access to interface 0. Does not work under windows. */ | 
      
        |  |  | 296 |   ret = usb_claim_interface(handle, 0); | 
      
        |  |  | 297 |   if (ret != 0) { | 
      
        |  |  | 298 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 299 |  | 
      
        |  |  | 300 |     exit(1); | 
      
        |  |  | 301 |   } | 
      
        |  |  | 302 | #endif | 
      
        |  |  | 303 |  | 
      
        |  |  | 304 |   printf("writing to adapter");   | 
      
        |  |  | 305 |   i2c_tiny_usb_write(0,0,0); | 
      
        |  |  | 306 |  | 
      
        |  |  | 307 |   /* do some testing */ | 
      
        |  |  | 308 |   printf("Getting adapter functionalities"); | 
      
        |  |  | 309 |   i2c_tiny_usb_get_func(); | 
      
        |  |  | 310 |  | 
      
        |  |  | 311 |   /* try to set i2c clock to 100kHz (10us), will actually result in ~50kHz */ | 
      
        |  |  | 312 |   /* since the software generated i2c clock isn't too exact. in fact setting */ | 
      
        |  |  | 313 |   /* it to 10us doesn't do anything at all since this already is the default */ | 
      
        |  |  | 314 |   printf("Reseting I2C clock to 100 kHz"); | 
      
        |  |  | 315 |   i2c_tiny_usb_set(CMD_SET_DELAY, 10); | 
      
        |  |  | 316 |  | 
      
        |  |  | 317 |   /* -------- begin of ds1621 client processing --------- */ | 
      
        |  |  | 318 |   printf("Probing for DS1621 ... "); | 
      
        |  |  | 319 |  | 
      
        |  |  | 320 |   /* try to access ds1621 at address DS1621_ADDR */ | 
      
        |  |  | 321 |   if(usb_control_msg(handle, USB_CTRL_IN,  | 
      
        |  |  | 322 | 		     CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END, | 
      
        |  |  | 323 | 		     0, DS1621_ADDR, NULL, 0,  | 
      
        |  |  | 324 | 		     1000) < 0) { | 
      
        |  |  | 325 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 326 |     goto quit; | 
      
        |  |  | 327 |   }  | 
      
        |  |  | 328 |  | 
      
        |  |  | 329 |   if(i2c_tiny_usb_get_status() == STATUS_ADDRESS_ACK) { | 
      
        |  |  | 330 |     int temp; | 
      
        |  |  | 331 |  | 
      
        |  |  | 332 |     printf("success at address 0x%02x\n", DS1621_ADDR); | 
      
        |  |  | 333 |  | 
      
        |  |  | 334 |     /* activate one shot mode */ | 
      
        |  |  | 335 |     if(i2c_write_cmd_and_byte(DS1621_ADDR, 0xac, 0x01) < 0) | 
      
        |  |  | 336 |       goto quit; | 
      
        |  |  | 337 |  | 
      
        |  |  | 338 |     /* wait 10ms */ | 
      
        |  |  | 339 |     usleep(10000); | 
      
        |  |  | 340 |  | 
      
        |  |  | 341 | #if 0 | 
      
        |  |  | 342 |     /* write default limits */ | 
      
        |  |  | 343 |     /* high threshold: +15 deg celsius */ | 
      
        |  |  | 344 |     i2c_write_cmd_and_word(DS1621_ADDR, 0xa1, 0x0f00);  /* 15 deg celsius */ | 
      
        |  |  | 345 |     usleep(10000); | 
      
        |  |  | 346 |     /* low threshold: +10 deg celsius */ | 
      
        |  |  | 347 |     i2c_write_cmd_and_word(DS1621_ADDR, 0xa2, 0x0a00);   | 
      
        |  |  | 348 |     usleep(10000); | 
      
        |  |  | 349 | #endif | 
      
        |  |  | 350 |  | 
      
        |  |  | 351 |     /* display limits */ | 
      
        |  |  | 352 |     temp = i2c_read_with_cmd(DS1621_ADDR, 0xa1, 2); | 
      
        |  |  | 353 |     printf("high temperature threshold = %d.%03d\n",  | 
      
        |  |  | 354 | 	   temp>>8, 1000 * (temp & 0xff) / 256); | 
      
        |  |  | 355 |     temp = i2c_read_with_cmd(DS1621_ADDR, 0xa2, 2); | 
      
        |  |  | 356 |     printf("low temperature threshold = %d.%03d\n",  | 
      
        |  |  | 357 | 	   temp>>8, 1000 * (temp & 0xff) / 256); | 
      
        |  |  | 358 |  | 
      
        |  |  | 359 |     printf("Getting %d temperature readings:\n", LOOPS); | 
      
        |  |  | 360 |     for(i=0;i<LOOPS;i++) { | 
      
        |  |  | 361 |       int temp; | 
      
        |  |  | 362 |       int counter, slope; | 
      
        |  |  | 363 |  | 
      
        |  |  | 364 |       /* just write command 0xee to start conversion */ | 
      
        |  |  | 365 |       if(i2c_read_with_cmd(DS1621_ADDR, 0xee, 0) < 0)  | 
      
        |  |  | 366 | 	goto quit; | 
      
        |  |  | 367 |  | 
      
        |  |  | 368 |       ds1621_read_control(); | 
      
        |  |  | 369 |  | 
      
        |  |  | 370 |       temp = i2c_read_with_cmd(DS1621_ADDR, 0xaa, 2); | 
      
        |  |  | 371 |       if(temp < 0)  | 
      
        |  |  | 372 | 	goto quit; | 
      
        |  |  | 373 |  | 
      
        |  |  | 374 |       /* read counter and slope values */ | 
      
        |  |  | 375 |       counter = i2c_read_with_cmd(DS1621_ADDR, 0xa8, 1); | 
      
        |  |  | 376 |       slope = i2c_read_with_cmd(DS1621_ADDR, 0xa9, 1); | 
      
        |  |  | 377 |  | 
      
        |  |  | 378 |       /* use counter and slope to adjust temperature (see ds1621 datasheet) */ | 
      
        |  |  | 379 |       temp = (temp & 0xff00) - 256/4; | 
      
        |  |  | 380 |       temp += 256 * (slope - counter) / slope; | 
      
        |  |  | 381 |  | 
      
        |  |  | 382 |       printf("temp = %d.%03d\n", temp>>8, 1000 * (temp & 0xff) / 256); | 
      
        |  |  | 383 |     } | 
      
        |  |  | 384 |   } else | 
      
        |  |  | 385 |     printf("failed\n"); | 
      
        |  |  | 386 |   /* -------- end of ds1621 client processing --------- */ | 
      
        |  |  | 387 |  | 
      
        |  |  | 388 |   /* -------- begin of pcf8574 client processing --------- */ | 
      
        |  |  | 389 |   printf("Probing for PCF8574 ... "); | 
      
        |  |  | 390 |  | 
      
        |  |  | 391 |   /* try to access pcf8574 at address PCF8574_ADDR */ | 
      
        |  |  | 392 |   if(usb_control_msg(handle, USB_CTRL_IN,  | 
      
        |  |  | 393 | 		     CMD_I2C_IO + CMD_I2C_BEGIN + CMD_I2C_END, | 
      
        |  |  | 394 | 		     0, PCF8574_ADDR, NULL, 0,  | 
      
        |  |  | 395 | 		     1000) < 0) { | 
      
        |  |  | 396 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 397 |     goto quit; | 
      
        |  |  | 398 |   }  | 
      
        |  |  | 399 |  | 
      
        |  |  | 400 |   if(i2c_tiny_usb_get_status() == STATUS_ADDRESS_ACK) { | 
      
        |  |  | 401 |     unsigned char bit_mask = 0xfe; | 
      
        |  |  | 402 |  | 
      
        |  |  | 403 |     printf("success at address 0x%02x\n", PCF8574_ADDR); | 
      
        |  |  | 404 |  | 
      
        |  |  | 405 |     printf("Cycling 0 bit %d times.\n", LOOPS); | 
      
        |  |  | 406 |     /* just rotate a single 0 bit through the outputs */ | 
      
        |  |  | 407 |  | 
      
        |  |  | 408 |     for(i=0;i<LOOPS;i++) { | 
      
        |  |  | 409 |       if(i2c_write_byte(PCF8574_ADDR, bit_mask) < 0) | 
      
        |  |  | 410 | 	goto quit; | 
      
        |  |  | 411 |  | 
      
        |  |  | 412 |       /* rotate the byte */ | 
      
        |  |  | 413 |       bit_mask = (bit_mask << 1) | 1; | 
      
        |  |  | 414 |       if(bit_mask == 0xff)  | 
      
        |  |  | 415 | 	bit_mask = 0xfe; | 
      
        |  |  | 416 |  | 
      
        |  |  | 417 |       usleep(100000); | 
      
        |  |  | 418 |     } | 
      
        |  |  | 419 |   } else | 
      
        |  |  | 420 |     printf("failed\n"); | 
      
        |  |  | 421 |   /* -------- end of pcf8574 client processing --------- */ | 
      
        |  |  | 422 |  | 
      
        |  |  | 423 |  quit: | 
      
        |  |  | 424 | #ifndef WIN | 
      
        |  |  | 425 |   ret = usb_release_interface(handle, 0); | 
      
        |  |  | 426 |   if (ret) | 
      
        |  |  | 427 |     fprintf(stderr, "USB error: %s\n", usb_strerror()); | 
      
        |  |  | 428 | #endif | 
      
        |  |  | 429 |  | 
      
        |  |  | 430 |   usb_close(handle); | 
      
        |  |  | 431 |  | 
      
        |  |  | 432 | #ifdef WIN | 
      
        |  |  | 433 |   printf("Press return to quit\n"); | 
      
        |  |  | 434 |   getchar(); | 
      
        |  |  | 435 | #endif | 
      
        |  |  | 436 |  | 
      
        |  |  | 437 |   return 0; | 
      
        |  |  | 438 | } |