1 // https://github.com/ManuelSchneid3r/RaspberryPi/raw/master/sensors/src/tmp.c
5 #include <linux/i2c-dev.h>
12 void print_usage(char * appname) {
13 printf("Usage: %s [--resolution|-r<0-3>][--faultqueue|-f<0-3>][--oneshot|--nooneshot][--activehigh|--activelow][--interruptmode|--comparatormode][--shutdownmode|--noshutdownmode][--query] <i2c char device> <hex address>\n", appname);
16 void print_help(char * appname) {
20 "\t--shutdownmode, --noshutdownmode\n"
21 "\t\tThe Shutdown Mode allows the user to save maximum power by shutting down all device circuitry other than the serial interface, which reduces current consumption to typically less than 0.1 μA.\n\n"
22 "\t--oneshot, --nooneshot\n"
23 "\t\tThe TMP175 and TMP75 feature a One-Shot Temperature Measurement Mode. When the device is in Shutdown Mode, writing 1 to the OS bit will start a single temperature conversion. The device will return to the shutdown state at the completion of the single conversion. This is useful to reduce power consumption in the TMP175 and TMP75 when continuous temperature monitoring is not required.\n\n"
24 "\t--interruptmode, --comparatormode\n"
25 "\t\tThe Thermostat Mode bit of the TMP175 and TMP75 indicates to the device whether to operate in Comparator Mode or Interrupt Mode (Alert pin). In Comparator mode, the ALERT pin is activated when the temperature equals or exceeds the value in the T(HIGH) register and it remains active until the temperature falls below the value in the T(LOW)register. In Interrupt mode, the ALERT pin is activated when the temperature exceeds T(HIGH) or goes below T(LOW) registers. The ALERT pin is cleared when the host controller reads the temperature register. For more information see the sensors datasheet.\n\n"
26 "\t--activehigh, --activelow\n"
27 "\t\tThe Polarity Bit of the TMP175 lets the user adjust the polarity of the ALERT pin output. If the POL bit is set to 0 (default), the ALERT pin becomes active low. When POL bit is set to 1, the ALERT pin becomes active high and the state of the ALERT pin is inverted.\n\n"
28 "\t--faultqueue, -f=N\n"
29 "\t\tA fault condition is defined as when the measured temperature exceeds the user-defined limits set in the THIGH and TLOW Registers. Additionally, the number of fault conditions required to generate an alert may be programmed using the Fault Queue. The Fault Queue is provided to prevent a false alert as a result of environmental noise. The Fault Queue requires consecutive fault measurements in order to trigger the alert function.\n\n"
30 "\t--resolution, -r={0, 1, 2, 3}\n"
31 "\t\tThe Converter Resolution Bits control the resolution of the internal analog-to-digital (ADC) converter. This control allows the user to maximize efficiency by programming for higher resolution or faster conversion time. \n\n"
32 "\tR\tRESOLUTION\t(TYPICAL) CONVERSION TIME \n"
33 "\t0\t0.5°C\t\t27.5 ms\n"
34 "\t1\t0.25°C\t\t55 ms\n"
35 "\t2\t0.125°C\t\t110 ms\n"
36 "\t3\t0.0625°C\t220 ms\n"
38 "\t\tQueries the current cofiguration.\n\n"
40 "\t\tPrint this help\n\n"
41 "Author: Manuel Schneider manuelschneid3r@googles mail server\n"
45 void err_write(int fd, const void *buf, size_t count) {
46 if ((write(fd, buf, count)) != count) {
47 printf("Error writing to i2c slave.\n");
52 void err_read(int fd, void *buf, size_t count) {
53 if (read(fd, buf, count) != count) {
54 printf("Unable to read from slave.\n");
60 int OS; // Oneshot mode bool
61 int RES; // Resolution 0-3
62 int FQ; // Faultqueue 0-3
63 int POL; // Polarity bool
64 int TM; // Termostat xor
65 int SD; // Shutdownmode bool
68 int main(int argc, char **argv)
70 static struct config_t config = {-1,-1,-1,-1,-1,-1};
75 static struct option long_options[] =
77 {"oneshot", no_argument, &config.OS, 1},
78 {"nooneshot", no_argument, &config.OS, 0},
79 {"resolution", required_argument, 0, 'r'},
80 {"faultqueue", required_argument, 0, 'f'},
81 {"activehigh", no_argument, &config.POL, 1},
82 {"activelow", no_argument, &config.POL, 0},
83 {"interruptmode", no_argument, &config.TM, 1},
84 {"comparatormode", no_argument, &config.TM, 0},
85 {"shutdownmode", no_argument, &config.SD, 1},
86 {"noshutdownmode", no_argument, &config.SD, 0},
87 {"query", no_argument, 0, 'q'},
88 {"help", no_argument, &help, 1},
93 * Get the parameters and set the relevant flags for operation.
96 while ((c = getopt_long (argc, argv, "qr:f:",
97 long_options, &option_index)) != -1)
102 // getopt_long set flag to val
108 config.FQ = atoi(optarg);
109 if (config.FQ < 0 || config.FQ > 3){
110 printf("Invalid fault queue parameter\n");
115 config.RES = atoi(optarg);
116 if (config.RES < 0 || config.RES > 3){
117 printf("Invalid resoltion parameter\n");
122 /* getopt_long already printed an error message. */
129 // Print help if requested
135 // Print usage mesage in case of a wrong amount of params
136 if ((argc-optind) != 2){
137 print_usage(argv[0]);
142 * Now start with the initializaton of the communication
144 // Open port for reading and writing
146 if ((fd = open(argv[optind], O_RDWR)) < 0) {
147 printf("Failed to open i2c port. Root?\n");
151 // Set the port options and the address of the device we wish to speak to
152 int address = strtol(argv[optind+1], NULL, 0);
153 if (ioctl(fd, I2C_SLAVE, address) < 0) {
154 printf("Unable to get bus access to talk to slave.\n");
160 * If the program was called with any of the configuration parameters get the
161 * config resister, modifiy it and write it bac to the IC.
163 if (config.OS != -1 || config.RES != -1 || config.FQ != -1 ||
164 config.POL != -1 || config.TM != -1 || config.SD != -1) {
165 // Set register pointer on IC to config register
166 unsigned char buf[2] = {1, 0};
167 err_write(fd, buf, 1);
169 // Read configuration register
170 err_read(fd, buf+1, 1);
172 // Set or unset the bits
174 config.OS ? buf[1]|(1<<7) : buf[1]&~(1<<7);
175 if (config.RES != -1){
176 buf[1]&=~(3<<5); // Unset the resolution
177 buf[1]|=config.RES<<5; //Set the resolution
179 if (config.FQ != -1){
180 buf[1]&=~(3<<3); // Unset the FQ
181 buf[1]|=config.FQ<<3; //Set the FQ
183 if (config.POL != -1)
184 config.POL ? buf[1]|(1<<2) : buf[1]&~(1<<2) ;
186 config.TM ? buf[1]|(1<<1) : buf[1]&~(1<<1) ;
188 config.SD ? buf[1]|(1<<0) : buf[1]&~(1<<0) ;
190 // Write the register back to the IC
191 err_write(fd, buf, 2);
193 // Query an pretty print the config
199 * If this is a query prettyprint the config register to stdout
202 // Set register pointer on IC to config register
203 unsigned char buf[2] = {1, 0};
204 err_write(fd, buf, 1);
206 // Read configuration register
207 err_read(fd, buf+1, 1);
209 // Pretty print config register
210 int resolution = ((buf[1] & (3<<5)) >> 5);
211 int fault_queue = ((buf[1] & (3<<3)) >> 3);
212 printf("Oneshot: %s\n", (buf[1] & (1<<7)) ? "Enabled" : "Disabled" );
213 printf("Resolution: %d (%.4f)\n", resolution, 1/pow(2, 1 + resolution));
214 printf("Fault queue: %d\n", fault_queue);
215 printf("Alert pin: Active %s\n", (buf[1] & (1<<2)) ? "high" : "low" );
216 printf("Thermostat mode: %s mode\n", (buf[1] & (1<<1)) ? "Interrupt" : "Comparator" );
217 printf("Shutdown mode: %s\n", (buf[1] & (1<<0)) ? "Enabled" : "Disabled" );
222 * If this was not a config query get the temperature and quit
224 // Send register to read from. "0"/temperature register
225 unsigned char buf[2]={0,0};
226 err_write(fd, buf, 1);
228 // Read back data into buf[]
229 err_read(fd, buf, 2);
231 // Compute the result
232 signed short data = (buf[0]<<8)|buf[1];
233 printf("%.1f\n", (float)data/256);