#include #include #include #include #include #include //# isdigit() #include "lm75.h" #include "deftypes.h" extern uint16 devicef; extern void bus_err(int ern); extern void print_help(void); extern uchar *xchg_data (uchar *buf, uint8 wrlen, uint8 waitlen, uint8 rdlen); uchar buf[32]; void lm75_print_all(void) { printf( "============ LM75xx interface ===========\n" "Registers:\n" " 00: Temperature data [°C] (reg: 0x00)\n" " 01: Configuration [hex] (reg: 0x01)\n" " 02: Tos (Overtemp) [°C] (reg: 0x03)\n" " 03: Thys (Hysteresis) [°C] (reg: 0x04)\n" "Configuration:\n" " tos: Over-Temperature register [-55°C...+125°C]\n" " thys: Temperature-hysteresis register [-55°C...+125°C]\n" " conf: Configuration register [hexadecimal]\n" " sleep: Set idle mode [on/off]\n" " mode: Comparator/Interrupt mode [comp/int]\n" " tos_pol: Tos pin polarity (Low/High) [Al/Ah]\n" " fault_q: Fault queue length [1/2/4]\n" "\n"); } // uchar *xchg_data (uchar *buf, uint8 wrlen, uint8 waitlen, uint8 rdlen){ //# [buf] = 32 byte // if(write(devicef, buf, wrlen) != wrlen){ //# write one byte to device // bus_err(errno); // } // usleep(waitlen*1000); //# Wait 10ms for reading // if(read(devicef, buf, rdlen) != rdlen) { //# read the result // bus_err(errno); // } // return buf; // } static float calc_temp(float offset){ // Calculate temperature uint16 rawtemp = 0; //# Signed by default float temp; buf[0] = 0x00; //# Measurement in the REG[0] xchg_data(buf,1,0,2); //# Write: 1byte addr, Read: 2byte data, Wait:0, [buf] = 32 byte rawtemp = (buf[0]*256 + buf[1]) >> 5; //# /x*256 == x << 8/ (>> 5): Temp is 11bit data register if((rawtemp & 0x400) == 0x400){ //# check if the msb(bit11) is 1 (1024 = 0x400), 2'complement negative number rawtemp = ~rawtemp + 1; //# 2'complement data rawtemp = rawtemp & 0x7ff; //# Only the lowest 11bit needed temp = -1 * rawtemp * 0.125 ; } else { temp = rawtemp * 0.125 ; //# 11bit -> 0.125°C or 9bit -> 0.5°C } return (temp + offset); } static float read_tos(void){ // Over-Temperature Shutdown register uint16 rawtemp = 0; //# Int16 default signed buf[0] = 0x03; //# Tos = REG[2] xchg_data(buf,1,0,2); rawtemp = buf[0]*256 + buf[1]; // x*256 == x << 8 rawtemp = (rawtemp) >> 7; //# 9bit data if((rawtemp & 0x100) == 0x100){ //# check MSB if it's a 2'complement number rawtemp = ~rawtemp + 1 ; //# 2'complement, 2^9 = 512; rawtemp = rawtemp & 0x1FF; //# lowest 9 bit return (-1 * rawtemp * 0.5); } else { return (rawtemp * 0.5); //# 9bit -> 0.5 celsius } } static float read_thys(void){ // Over-Temp Hysteresis Register uint16 rawtemp = 0; //# signed buf[0] = 0x02; xchg_data(buf,1,0,2); //# read from REG[3] rawtemp = (buf[0] << 8) + buf[1]; rawtemp = (rawtemp) >> 7; //# 9bit data if((rawtemp & 256) == 256){ //# 256 = 0x100 rawtemp = ~rawtemp + 1 ; //# 2'complement, 2^9 = 512; rawtemp = rawtemp & 0x1FF; //# lowest 9 bit return (-1 * rawtemp * 0.5); } return (rawtemp * 0.5); //# 9bit -> 0.5 celsius } static uchar read_conf(void){ //Configuration register buf[0] = 0x01; xchg_data(buf,1,0,1); return buf[0]; } void lm75_read_all(const uchar *opts){ // Print out whole device's data // if(opts != NULL) // { // printf("00:%f\n", calc_temp(strtof(opts, NULL))); // } else { printf("00:%f\n", calc_temp(0.0)); // } printf("01:0x%x\n", read_conf()); printf("02:%f\n", read_thys()); printf("03:%f\n", read_tos()); } void lm75_read_one(const uchar *opts){ // Prints the selected register's data uint16 id,i; uchar temp[256]; if(opts != NULL){ //# Search the comma: ...<01,-11.24> for(i = 0; i < strlen((char*)opts); i++){ if (*(opts+i) == ','){ break; } else { if( !isdigit(*(opts+i)) ){ //# Check the register string printf("The Register address must be an integer!\n"); print_help(); lm75_print_all(); exit (EXIT_FAILURE); } temp[i] = *(opts+i); //# copy register string temp[i+1] = '\0'; } } id = atoi((char*)temp); //# Convert register to number strncpy((char*)temp, (char*)opts+i+1, 255); //# Copy remain to temp switch (id) //# Which register is selected? { case 0x00: printf("%f\n", calc_temp(atof((char*)temp))); //# with the offset break; case 0x01: printf("0x%x\n", read_conf()); break; case 0x02: printf("%f\n", read_thys()); break; case 0x03: printf("%f\n", read_tos()); break; default: print_help(); } } } void lm75_conf_set(const uchar *opts){ // Prints the selected register's data uint16 i; uchar temp[256]; if(opts != NULL){ for(i = 0; i < strlen((char*)opts); i++){ if (*(opts+i) == ','){ //# .... conf_set 0x49 thys,-10.5 break; } temp[i] = *(opts+i); temp[i+1] = '\0'; } if(!strcmp("tos", (char*)temp)){ //# Set the Tos register value float inp; uint16 temp; buf[0] = 0x03; inp = atof( (char*)(opts+i+1)); if(inp < 0){ temp = 0 - inp/0.5; temp = ~temp +1; //# 2'complement buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) buf[2] = ((temp << 7) | 0x7F) & 0xFF; //# |d8,d7,d6,d5|d4,d3,d2,d1|d0,xx,xx,xx|xx,xx,xx,xx| } else { temp = inp/0.5; buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) buf[2] = (temp << 7) & 0xFF;; } xchg_data(buf,3,0,2); }else if(!strcmp("thys", (char*)temp)){ //# Set the Thys reg float inp; uint16 temp; buf[0] = 0x02; inp = atof( (char*)(opts+i+1)); if(inp < 0){ temp = 0 - inp/0.5; temp = ~temp +1; //# 2'complement buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) buf[2] = ((temp << 7) | 0x7F) & 0xFF; //# |d8,d7,d6,d5|d4,d3,d2,d1|d0,xx,xx,xx|xx,xx,xx,xx| } else { temp = inp/0.5; buf[1] = (temp >> 1) & 0xFF; //# (x << 7) and (x >> 8) ==> (x >> 1) buf[2] = (temp << 7) & 0xFF;; } xchg_data(buf,3,0,2); }else if(!strcmp("conf", (char*)temp)){ //# Set whole conf register buf[0] = 0x01; buf[1] = strtol((char*)(opts+i+1),NULL,0); xchg_data(buf,2,0,1); }else if(!strcmp("sleep", (char*)temp)){ //# Send the sleep command buf[0] = 0x01; xchg_data(buf,1,0,1); if (!strcmp("on",(char*)opts+i+1)) { buf[1] = buf[0] | 0x01; } else if(!strcmp("off",(char*)opts+i+1)) { // buf[1] = ~buf[0]; //# XOR = NEG->OR->NEG // buf[1] = buf[1] | 0b00000001; //# Invert->add->invert // buf[1] = ~buf[1]; buf[1] = buf[0] ^ 0b00000001; //# XOR to clear the bit } else { lm75_print_all(); exit(EXIT_FAILURE); } buf[0] = 0x01; xchg_data(buf,2,0,1); }else if(!strcmp("mode", (char*)temp)){ //# Comparator/Interrupt mode buf[0] = 0x01; xchg_data(buf,1,0,1); if (!strcmp("comp",(char*)opts+i+1)) { buf[1] = buf[0] ^ 0b00000010; //# XOR to clear } else if(!strcmp("int",(char*)opts+i+1)) { buf[1] = buf[0] | 0b00000010; } else { lm75_print_all(); exit(EXIT_FAILURE); } buf[0] = 0x01; xchg_data(buf,2,0,1); }else if(!strcmp("tos_pol", (char*)temp)){ //# Tos polarity buf[0] = 0x01; xchg_data(buf,1,0,1); if (!strcmp("Al",(char*)opts+i+1)) { buf[1] = buf[0] ^ 0b00000100; //# XOR to clear the bit } else if(!strcmp("Ah",(char*)opts+i+1)) { buf[1] = buf[0] | 0b00000100; } else { lm75_print_all(); exit(EXIT_FAILURE); } buf[0] = 0x01; xchg_data(buf,2,0,1); }else if(!strcmp("fault_q", (char*)temp)){ //# Tos Fault Queue buf[0] = 0x01; xchg_data(buf,1,0,1); if (!strcmp("1",(char*)opts+i+1)) { buf[1] = buf[0] | 0b00011000; //# Add and clear whole section buf[1] = buf[1] ^ 0b00011000; } else if(!strcmp("2",(char*)opts+i+1)) { buf[1] = buf[0] | 0b00011000; //# Clear first buf[1] = buf[1] ^ 0b00011000; //# Clear first buf[1] = buf[1] | 0b00001000; //# Set } else if(!strcmp("4",(char*)opts+i+1)) { buf[1] = buf[0] | 0b00011000; //# Clear first buf[1] = buf[1] ^ 0b00011000; //# Clear first buf[1] = buf[1] | 0b00010000; //# Set } else { lm75_print_all(); exit(EXIT_FAILURE); } buf[0] = 0x01; xchg_data(buf,2,0,1); } else { // for(i = 0; i < strlen((char*)opts); i++ ){ // if( !isxdigit(*(opts+i)) || *(opts+i) !='x' || opts[i] != ','){ //# Check the register string // printf("The Register address, and value must be a hex, or an integer!\n"); print_help(); lm75_print_all(); exit (EXIT_FAILURE); // } // } } } }