#include #include #include #include #include #include #include #define DEV "/dev/i2c/0" // Status register bits #define STATUS_DIR 0x80 #define STATUS_TSB 0x40 #define STATUS_SBR 0x20 #define STATUS_RST 0x10 #define STATUS_LL 0x08 #define STATUS_SD 0x04 #define STATUS_PPD 0x02 #define STATUS_1WB 0x01 typedef unsigned long long int owaddress; int i2cdev; void i2c_write(unsigned char* cmd, int buflen) { if (write(i2cdev, cmd, buflen) != buflen) perror("cmd_write"); } unsigned char ow_wait() { unsigned char buf = 0xFF; do { read(i2cdev, &buf, 1); } while (buf & STATUS_1WB); return buf; } void ow_reset() { unsigned char status; i2c_write("\xF0", 1); // Device reset i2c_write("\xD2\xF0", 2); // Config write i2c_write("\xB4", 1); // 1 wire reset status = ow_wait(); printf("Initialization complete, "); if (status & STATUS_SD) printf("bus is shorted\n"); else if (status & STATUS_PPD) printf("presence pulse detected\n"); else printf("no devices detected\n"); } void ow_backtostart() { i2c_write("\xB4", 1); // 1 wire reset ow_wait(); i2c_write("\xA5\xF0", 2); // Search bus ow_wait(); } unsigned char ow_triplet(int direction) { unsigned char buf[2], status; buf[0] = 0x78; buf[1] = direction ? 0x80 : 0x00; i2c_write(buf, 2); status = ow_wait(); // printf(", dgo %d, dwent %d, first %d, second %d", // direction ? 1 : 0, status & STATUS_DIR ? 1 : 0, // status & STATUS_SBR ? 1 : 0, status & STATUS_TSB ? 1 :0); return status; } void ow_selectaddr(owaddress addr) { i2c_write("\xB4", 1); // 1 wire reset ow_wait(); unsigned char buf[2]; int i; i2c_write("\xA5\x55", 2); // Match rom ow_wait(); for (i = 0; i < 8; i++) { buf[0] = 0xA5; buf[1] = addr & 0xFF; i2c_write(buf, 2); ow_wait(); addr = addr >> 8; } } int ow_crc(owaddress addr) { int i, bit_in; unsigned char crc = 0x00; for (i = 0; i < 64; i++) { bit_in = addr & 0x01; addr = addr >> 1; if (crc & 0x01) bit_in = 1 - bit_in; crc = crc >> 1; if (bit_in) crc ^= 0x80 | 0x08 | 0x04; } printf("Result crc 0x%02x addr 0x%llx\n", crc, addr); if (crc == 0) return 1; else return 0; } float ow_temp_ds18s20(owaddress addr) { unsigned char stratchpad[9]; int i; ow_selectaddr(addr); i2c_write("\xD2\xB4", 2); // Enable SPU i2c_write("\xA5\x44", 2); // Convert_T usleep(800000); i2c_write("\xD2\xF0", 2); // Disable SPU ow_selectaddr(addr); i2c_write("\xA5\xBE", 2); // Read stratchpad ow_wait(); printf("Stratchpad "); for (i = 0; i < 9; i++) { i2c_write("\x96", 1); ow_wait(); i2c_write("\xE1\xE1", 2); if (read(i2cdev, stratchpad + i, 1) != 1) perror("i2c_read"); printf("%02x ", *(stratchpad + i)); } printf("\n"); int temp_read, count_remain, count_per_c; float result; temp_read = stratchpad[0] >> 1; if (stratchpad[1]) temp_read = - temp_read; count_remain = stratchpad[6]; count_per_c = stratchpad[7]; result = temp_read - 0.25 + ((float) count_per_c - count_remain) / count_per_c; return result; } void ow_scan() { owaddress path_here, path_follow, path_follow_next = 0; int depth, status, done = 0; // We kind of walk a binary tree depth-first while(!done) { ow_backtostart(); depth = 0; path_here = 0; path_follow = path_follow_next; done = 1; printf("New loop\n"); while (depth < 64) { // printf("Depth %d", depth); status = ow_triplet(path_follow & (1 << depth)); if (status & STATUS_DIR) { path_here |= (owaddress) 1 << depth; } else if ((status & (STATUS_SBR | STATUS_TSB)) == 0x00) { // Two devices at this bit, and we went left // Next time: follow path this far, then turn right done = 0; path_follow_next = ((((owaddress) 1 << depth) - 1) & path_here) | ((owaddress) 1 << depth); } depth++; } int c = ow_crc(path_here); printf("GOT ADDRESS!!!!!!!: 0x%016llx %s\n", path_here, c ? "valid" : "INVALID!"); if ((path_here & 0xFF) == 0x10) printf("Temperature %0.2f\n", ow_temp_ds18s20(path_here)); } } int main() { i2cdev = open(DEV, O_RDWR); if (i2cdev < 0) { perror("open"); exit(1); } ioctl(i2cdev, I2C_SLAVE, 0x18); ow_reset(); ow_scan(); return 0; }