libcollectdclient: Propagate errors when signing / encrypting network packets.
[collectd.git] / src / barometer.c
1 /**
2  * collectd - src/barometer.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; only version 2.1 of the License is
7  * applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors:
19  *   Tomas Menzl
20  **/
21
22 #include "collectd.h"
23 #include "common.h"
24 #include "utils_cache.h"
25 #include "plugin.h"
26
27 #include <stdint.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <linux/i2c-dev.h>
31 #include <math.h>
32
33 /* ------------ MPL115 defines ------------ */
34 /* I2C address of the MPL115 sensor */
35 #define MPL115_I2C_ADDRESS          0x60
36                                     
37 /* register addresses */            
38 #define MPL115_ADDR_CONV            0x00
39 #define MPL115_ADDR_COEFFS          0x04
40                                     
41 /* register sizes */                
42 #define MPL115_NUM_CONV             4
43 #define MPL115_NUM_COEFFS           12
44                                     
45 /* commands / addresses */          
46 #define MPL115_CMD_CONVERT_PRESS    0x10
47 #define MPL115_CMD_CONVERT_TEMP     0x11
48 #define MPL115_CMD_CONVERT_BOTH     0x12
49                                     
50 #define MPL115_CONVERSION_RETRIES   5
51
52
53 /* ------------ MPL3115 defines ------------ */
54 /* MPL3115 I2C address */
55 #define MPL3115_I2C_ADDRESS         0x60
56
57 /* register addresses (only the interesting ones) */
58 #define MPL3115_REG_STATUS          0x00
59 #define MPL3115_REG_OUT_P_MSB       0x01
60 #define MPL3115_REG_OUT_P_CSB       0x02
61 #define MPL3115_REG_OUT_P_LSB       0x03
62 #define MPL3115_REG_OUT_T_MSB       0x04
63 #define MPL3115_REG_OUT_T_LSB       0x05
64 #define MPL3115_REG_DR_STATUS       0x06
65 #define MPL3115_REG_WHO_AM_I        0x0C
66 #define MPL3115_REG_SYSMOD          0x11
67 #define MPL3115_REG_PT_DATA_CFG     0x13
68 #define MPL3115_REG_BAR_IN_MSB      0x14
69 #define MPL3115_REG_BAR_IN_LSB      0x15
70 #define MPL3115_REG_CTRL_REG1       0x26
71 #define MPL3115_REG_CTRL_REG2       0x27
72 #define MPL3115_REG_CTRL_REG3       0x28
73 #define MPL3115_REG_CTRL_REG4       0x29
74 #define MPL3115_REG_CTRL_REG5       0x2A
75 #define MPL3115_REG_OFF_P           0x2B
76 #define MPL3115_REG_OFF_T           0x2C
77 #define MPL3115_REG_OFF_H           0x2D
78
79 /* Register values, masks */
80 #define MPL3115_WHO_AM_I_RESP       0xC4
81
82 #define MPL3115_PT_DATA_DREM        0x04
83 #define MPL3115_PT_DATA_PDEF        0x02
84 #define MPL3115_PT_DATA_TDEF        0x01
85                                     
86 #define MPL3115_DR_STATUS_TDR       0x02
87 #define MPL3115_DR_STATUS_PDR       0x04
88 #define MPL3115_DR_STATUS_PTDR      0x08
89 #define MPL3115_DR_STATUS_DR        (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
90                                     
91 #define MPL3115_DR_STATUS_TOW       0x20
92 #define MPL3115_DR_STATUS_POW       0x40
93 #define MPL3115_DR_STATUS_PTOW      0x80
94
95 #define MPL3115_CTRL_REG1_ALT       0x80
96 #define MPL3115_CTRL_REG1_RAW       0x40
97 #define MPL3115_CTRL_REG1_OST_MASK  0x38
98 #define MPL3115_CTRL_REG1_OST_1     0x00
99 #define MPL3115_CTRL_REG1_OST_2     0x08
100 #define MPL3115_CTRL_REG1_OST_4     0x10
101 #define MPL3115_CTRL_REG1_OST_8     0x18
102 #define MPL3115_CTRL_REG1_OST_16    0x20
103 #define MPL3115_CTRL_REG1_OST_32    0x28
104 #define MPL3115_CTRL_REG1_OST_64    0x30
105 #define MPL3115_CTRL_REG1_OST_128   0x38
106 #define MPL3115_CTRL_REG1_RST       0x04
107 #define MPL3115_CTRL_REG1_OST       0x02
108 #define MPL3115_CTRL_REG1_SBYB      0x01
109 #define MPL3115_CTRL_REG1_SBYB_MASK 0xFE
110
111 #define MPL3115_NUM_CONV_VALS       5
112
113
114 /* ------------ BMP085 defines ------------ */
115 /* I2C address of the BMP085 sensor */
116 #define BMP085_I2C_ADDRESS          0x77
117
118 /* register addresses */            
119 #define BMP085_ADDR_ID_REG          0xD0
120 #define BMP085_ADDR_VERSION         0xD1
121
122 #define BMP085_ADDR_CONV            0xF6
123
124 #define BMP085_ADDR_CTRL_REG        0xF4
125 #define BMP085_ADDR_COEFFS          0xAA
126
127 /* register sizes */                
128 #define BMP085_NUM_COEFFS           22
129
130 /* commands, values */
131 #define BMP085_CHIP_ID              0x55
132
133 #define BMP085_CMD_CONVERT_TEMP     0x2E
134
135 #define BMP085_CMD_CONVERT_PRESS_0  0x34
136 #define BMP085_CMD_CONVERT_PRESS_1  0x74
137 #define BMP085_CMD_CONVERT_PRESS_2  0xB4
138 #define BMP085_CMD_CONVERT_PRESS_3  0xF4
139
140 /* in us */
141 #define BMP085_TIME_CNV_TEMP        4500
142
143 #define BMP085_TIME_CNV_PRESS_0     4500
144 #define BMP085_TIME_CNV_PRESS_1     7500
145 #define BMP085_TIME_CNV_PRESS_2    13500
146 #define BMP085_TIME_CNV_PRESS_3    25500
147
148
149 /* ------------ Normalization ------------ */
150 /* Mean sea level pressure normalization methods */
151 #define MSLP_NONE          0
152 #define MSLP_INTERNATIONAL 1
153 #define MSLP_DEU_WETT      2
154
155 /** Temperature reference history depth for averaging. See #get_reference_temperature */
156 #define REF_TEMP_AVG_NUM   5
157
158
159 /* ------------------------------------------ */
160
161 /** Supported sensor types */
162 enum Sensor_type {
163     Sensor_none = 0,
164     Sensor_MPL115,
165     Sensor_MPL3115,
166     Sensor_BMP085
167 };
168
169 static const char *config_keys[] =
170 {
171     "Device",
172     "Oversampling",
173     "PressureOffset",    /**< only for MPL3115 */
174     "TemperatureOffset", /**< only for MPL3115 */
175     "Altitude",
176     "Normalization",
177     "TemperatureSensor"
178 };
179
180 static int    config_keys_num     = STATIC_ARRAY_SIZE(config_keys);
181                                   
182 static char * config_device       = NULL;  /**< I2C bus device */
183 static int    config_oversample   = 1;     /**< averaging window */
184
185 static double config_press_offset = 0.0;   /**< pressure offset */
186 static double config_temp_offset  = 0.0;   /**< temperature offset */
187
188 static double config_altitude     = NAN;   /**< altitude */
189 static int    config_normalize    = 0;     /**< normalization method */
190                                   
191 static _Bool  configured          = 0;     /**< the whole plugin config status */
192                                   
193 static int    i2c_bus_fd          = -1;    /**< I2C bus device FD */
194
195 static enum Sensor_type sensor_type = Sensor_none; /**< detected/used sensor type */
196
197 static __s32  mpl3115_oversample  = 0;    /**< MPL3115 CTRL1 oversample setting */
198
199 // BMP085 configuration
200 static unsigned      bmp085_oversampling; /**< BMP085 oversampling (0-3) */
201 static unsigned long bmp085_timeCnvPress; /**< BMP085 conversion time for pressure in us */
202 static __u8          bmp085_cmdCnvPress;  /**< BMP085 pressure conversion command */
203
204
205 /* MPL115 conversion coefficients */
206 static double mpl115_coeffA0;
207 static double mpl115_coeffB1;
208 static double mpl115_coeffB2;
209 static double mpl115_coeffC12;
210 static double mpl115_coeffC11;
211 static double mpl115_coeffC22;
212
213 /* BMP085 conversion coefficients */
214 static short bmp085_AC1;
215 static short bmp085_AC2;
216 static short bmp085_AC3;
217 static unsigned short bmp085_AC4;
218 static unsigned short bmp085_AC5;
219 static unsigned short bmp085_AC6;
220 static short bmp085_B1;
221 static short bmp085_B2;
222 static short bmp085_MB;
223 static short bmp085_MC;
224 static short bmp085_MD;
225
226
227
228 /* ------------------------ averaging ring buffer ------------------------ */
229 /*  Used only for MPL115. MPL3115 supports real oversampling in the device so */
230 /*  no need for any postprocessing. */
231
232 static _Bool avg_initialized = 0;    /**< already initialized by real values */
233
234 typedef struct averaging_s {
235     long int * ring_buffer;
236     int        ring_buffer_size;
237     long int   ring_buffer_sum;
238     int        ring_buffer_head;
239 } averaging_t;
240
241
242 static averaging_t pressure_averaging    = { NULL, 0, 0L, 0 };
243 static averaging_t temperature_averaging = { NULL, 0, 0L, 0 };
244
245
246 /** 
247  * Create / allocate averaging buffer
248  *
249  * The buffer is initialized with zeros.
250  *
251  * @param avg  pointer to ring buffer to be allocated
252  * @param size requested buffer size
253  *
254  * @return Zero when successful
255  */
256 static int averaging_create(averaging_t * avg, int size)
257 {
258     int a;
259
260     avg->ring_buffer = (long int *) malloc(size * sizeof(*avg));
261     if (avg->ring_buffer == NULL)
262     {
263         ERROR ("barometer: averaging_create - ring buffer allocation of size %d failed",
264                size);
265         return -1;
266     }
267
268     for (a=0; a<size; ++a)
269     {
270       avg->ring_buffer[a] = 0L;
271     }
272
273     avg->ring_buffer_size = size;
274     avg->ring_buffer_sum  = 0L;
275     avg->ring_buffer_head = 0;
276
277     return 0;
278 }
279
280
281 /**
282  * Delete / free existing averaging buffer
283  *
284  * @param avg  pointer to the ring buffer to be deleted
285  */
286 static void averaging_delete(averaging_t * avg)
287 {
288     if (avg->ring_buffer != NULL)
289     {
290         free(avg->ring_buffer);
291         avg->ring_buffer = NULL;
292     }
293     avg->ring_buffer_size = 0;
294     avg->ring_buffer_sum  = 0L;
295     avg->ring_buffer_head = 0;
296 }
297
298
299 /*
300  * Add new sample to the averaging buffer
301  *
302  * A new averaged value is returned. Note that till the buffer is full
303  * returned value is inaccurate as it is an average of real values and initial
304  * zeros.
305  *
306  * @param avg    pointer to the ring buffer
307  * @param sample new sample value
308  *
309  * @return Averaged sample value
310  */
311 static double averaging_add_sample(averaging_t * avg, long int sample)
312 {
313     double result;
314
315     avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head];
316     avg->ring_buffer[avg->ring_buffer_head] = sample;
317     avg->ring_buffer_head = (avg->ring_buffer_head+1) % avg->ring_buffer_size;
318     result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
319     
320     DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf", 
321            sample, 
322            result);
323
324     return result;
325 }
326
327
328 /* ------------------------ temperature refference ------------------------ */
329
330 /**
331  * Linked list type of temperature sensor references
332  */
333 typedef struct temperature_list_s {
334     char                      * sensor_name; /**< sensor name/reference */
335     size_t                      num_values;  /**< number of values (usually one) */
336     _Bool                       initialized; /**< sensor already provides data */
337     struct temperature_list_s * next;        /**< next in the list */
338 } temperature_list_t;
339
340 static temperature_list_t * temp_list = NULL;
341
342
343 /*
344  * Add new sensor to the temperature reference list
345  *
346  * @param list   the list
347  * @param sensor reference name (as provided by the config file)
348  *
349  * @return Zero when successful
350  */
351 static int temp_list_add(temperature_list_t * list, const char * sensor)
352 {
353     temperature_list_t * new_temp;
354
355     new_temp = (temperature_list_t *) malloc(sizeof(*new_temp));
356     if(new_temp == NULL)
357         return -1;
358
359     new_temp->sensor_name = strdup(sensor);
360     new_temp->initialized = 0;
361     new_temp->num_values = 0;
362     if(new_temp->sensor_name == NULL)
363     {
364         free(new_temp);
365         return -1;
366     }
367
368     new_temp->next = temp_list;
369     temp_list = new_temp;
370     return 0;
371 }
372
373
374 /*
375  * Delete the whole temperature reference list
376  *
377  * @param list the list to be deleted
378  */
379 static void temp_list_delete(temperature_list_t ** list)
380 {
381     temperature_list_t * tmp;
382
383     while (*list != NULL)
384     {
385         tmp = (*list);
386         (*list) = (*list)->next;
387         free(tmp->sensor_name);
388         free(tmp);
389         tmp = NULL;
390     }
391 }
392
393
394 /*
395  * Get reference temperature value
396  *
397  * First initially uc_get_rate_by_name is tried. At the startup due to nondeterministic
398  * order the temperature may not be read yet (then it fails and first measurment gives
399  * only absolute air pressure reading which is acceptable). Once it succedes (should be
400  * second measurement at the latest) we use average of few last readings from
401  * uc_get_history_by_name. It may take few readings to start filling so again we use
402  * uc_get_rate_by_name as a fallback.
403  * The idea is to use basic "noise" filtering (history averaging) across all the values
404  * which given sensor provides (up to given depth). Then we get minimum among
405  * the sensors.
406  *
407  * @param result where the result is stored. When not available NAN is stored.
408  *
409  * @return Zero when successful
410  */
411 static int get_reference_temperature(double * result)
412 {
413     temperature_list_t * list = temp_list;
414
415     gauge_t * values = NULL;   /**< rate values */
416     size_t    values_num = 0;  /**< number of rate values */
417     int i;
418
419     gauge_t values_history[REF_TEMP_AVG_NUM];
420
421     double avg_sum;  /**< Value sum for computing average */
422     int    avg_num;  /**< Number of values for computing average */
423     double average;  /**< Resulting value average */
424
425     *result = NAN;
426
427     while(list != NULL)
428     {
429         avg_sum = 0.0;
430         avg_num = 0;
431
432         /* First time need to read current rate to learn how many values are
433            there (typically for temperature it would be just one).
434            We do not expect dynamic changing of number of temperarure values
435            in runtime yet (are there any such cases?). */
436         if(!list->initialized)
437         {
438             if(uc_get_rate_by_name(list->sensor_name,
439                                    &values,
440                                    &values_num))
441             {
442                 DEBUG ("barometer: get_reference_temperature - rate \"%s\" not found yet",
443                        list->sensor_name);
444                 list = list->next;
445                 continue;
446             }
447
448             DEBUG ("barometer: get_reference_temperature - initialize \"%s\", %zu vals",
449                    list->sensor_name,
450                    values_num);
451
452             list->initialized = 1;
453             list->num_values = values_num;
454
455             for(i=0; i<values_num; ++i)
456             {
457                 DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
458                        i,
459                        values[i]);
460                 if(!isnan(values[i]))
461                 {
462                     avg_sum += values[i];
463                     ++avg_num;
464                 }
465             }
466             free(values);
467             values = NULL;
468         }
469
470         /* It is OK to get here the first time as well, in the worst case
471            the history will full of NANs. */
472         if(uc_get_history_by_name(list->sensor_name,
473                                   values_history,
474                                   REF_TEMP_AVG_NUM,
475                                   list->num_values))
476         {
477             ERROR ("barometer: get_reference_temperature - history \"%s\" lost",
478                    list->sensor_name);
479             list->initialized = 0;
480             list->num_values = 0;
481             list = list->next;
482             continue;
483         }
484             
485         for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
486         {
487             DEBUG ("barometer: get_reference_temperature - history %d: %lf",
488                    i,
489                    values_history[i]);
490             if(!isnan(values_history[i]))
491             {
492                 avg_sum += values_history[i];
493                 ++avg_num;
494             }
495         }
496
497         if(avg_num == 0)   /* still no history? fallback to current */
498         {
499             if(uc_get_rate_by_name(list->sensor_name,
500                                    &values,
501                                    &values_num))
502             {
503                 ERROR ("barometer: get_reference_temperature - rate \"%s\" lost",
504                        list->sensor_name);
505                 list->initialized = 0;
506                 list->num_values = 0;
507                 list = list->next;
508                 continue;
509             }
510
511             for(i=0; i<values_num; ++i)
512             {
513                 DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
514                        i,
515                        values[i]);
516                 if(!isnan(values[i]))
517                 {
518                     avg_sum += values[i];
519                     ++avg_num;
520                 }
521             }
522             free(values);
523             values = NULL;
524         }
525
526         if(avg_num == 0)
527         {
528             ERROR ("barometer: get_reference_temperature - could not read \"%s\"",
529                    list->sensor_name);
530             list->initialized = 0;
531             list->num_values = 0;
532         }
533         else
534         {
535             average = avg_sum / (double) avg_num;
536             if(isnan(*result))
537                 *result=average;
538             else if(*result>average)
539                 *result=average;
540         }
541         list = list->next;
542     }  /* while sensor list */
543     
544     if(*result == NAN)
545     {
546         ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
547         return -1;
548     }
549     DEBUG ("barometer: get_reference_temperature - temp is %lf", *result);
550     return 0;
551 }
552
553
554 /* ------------------------ MPL115 access ------------------------ */
555
556 /** 
557  * Detect presence of a MPL115 pressure sensor.
558  *
559  * Unfortunately there seems to be no ID register so we just try to read first
560  * conversion coefficient from device at MPL115 address and hope it is really
561  * MPL115. We should use this check as the last resort (which would be the typical
562  * case anyway since MPL115 is the least accurate sensor).
563  * As a sideeffect will leave set I2C slave address.
564  * 
565  * @return 1 if MPL115, 0 otherwise
566  */
567 static int MPL115_detect(void)
568 {
569     __s32 res;
570     char errbuf[1024];
571
572     if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0)
573     {
574         ERROR("barometer: MPL115_detect problem setting i2c slave address to 0x%02X: %s",
575               MPL115_I2C_ADDRESS,
576               sstrerror (errno, errbuf, sizeof (errbuf)));
577         return 0 ;
578     }
579
580     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS);
581     if(res >= 0)
582     {
583         DEBUG ("barometer: MPL115_detect - positive detection");
584         return 1;
585     }
586
587     DEBUG ("barometer: MPL115_detect - negative detection");
588     return 0;
589 }
590
591 /** 
592  * Read the MPL115 sensor conversion coefficients.
593  *
594  * These are (device specific) constants so we can read them just once.
595  *
596  * @return Zero when successful
597  */
598 static int MPL115_read_coeffs(void)
599 {
600     uint8_t mpl115_coeffs[MPL115_NUM_COEFFS]; 
601     int32_t res;
602
603     int8_t  sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
604     int8_t  sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
605     int16_t sia0, sib1, sib2, sic12, sic11, sic22;
606       
607     char errbuf[1024];
608
609     res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
610                                         MPL115_ADDR_COEFFS, 
611                                         MPL115_NUM_COEFFS, 
612                                         mpl115_coeffs);
613     if (res < 0)
614     {
615         ERROR ("barometer: MPL115_read_coeffs - problem reading data: %s",
616                sstrerror (errno, errbuf, sizeof (errbuf)));
617         return -1;
618     }
619    
620     /* Using perhaps less elegant/efficient code, but more readable. */
621     /* a0: 16total 1sign 12int 4fract 0pad */
622     sia0MSB = mpl115_coeffs[0];
623     sia0LSB = mpl115_coeffs[1];
624     sia0 = (int16_t) sia0MSB <<8;          /* s16 type, Shift to MSB */
625     sia0 += (int16_t) sia0LSB & 0x00FF;    /* Add LSB to 16bit number */
626     mpl115_coeffA0 = (double) (sia0);
627     mpl115_coeffA0 /= 8.0;                 /* 3 fract bits */
628     
629     /* b1: 16total 1sign 2int 13fract 0pad */
630     sib1MSB= mpl115_coeffs[2];
631     sib1LSB= mpl115_coeffs[3];
632     sib1 = sib1MSB <<8;                    /* Shift to MSB */
633     sib1 += sib1LSB & 0x00FF;              /* Add LSB to 16bit number */
634     mpl115_coeffB1 = (double) (sib1);
635     mpl115_coeffB1 /= 8192.0;              /* 13 fract */
636     
637     /* b2: 16total 1sign 1int 14fract 0pad */
638     sib2MSB= mpl115_coeffs[4];
639     sib2LSB= mpl115_coeffs[5];
640     sib2 = sib2MSB <<8;                     /* Shift to MSB */
641     sib2 += sib2LSB & 0x00FF;               /* Add LSB to 16bit number */
642     mpl115_coeffB2 = (double) (sib2);
643     mpl115_coeffB2 /= 16384.0;              /* 14 fract */
644
645     /* c12: 14total 1sign 0int 13fract 9pad */
646     sic12MSB= mpl115_coeffs[6];
647     sic12LSB= mpl115_coeffs[7];
648     sic12 = sic12MSB <<8;                   /* Shift to MSB only by 8 for MSB */
649     sic12 += sic12LSB & 0x00FF;
650     mpl115_coeffC12 = (double) (sic12);
651     mpl115_coeffC12 /= 4.0;                 /* 16-14=2 */
652     mpl115_coeffC12 /= 4194304.0;           /* 13+9=22 fract */
653
654     /* c11: 11total 1sign 0int 11fract 11pad */
655     sic11MSB= mpl115_coeffs[8];
656     sic11LSB= mpl115_coeffs[9];
657     sic11 = sic11MSB <<8;                   /* Shift to MSB only by 8 for MSB */
658     sic11 += sic11LSB & 0x00FF;
659     mpl115_coeffC11 = (double) (sic11);
660     mpl115_coeffC11 /= 32.0;               /* 16-11=5 */
661     mpl115_coeffC11 /= 4194304.0;          /* 11+11=22 fract */
662
663     /* c12: 11total 1sign 0int 10fract 15pad */
664     sic22MSB= mpl115_coeffs[10];
665     sic22LSB= mpl115_coeffs[11];
666     sic22 = sic22MSB <<8;                   /* Shift to MSB only by 8 for MSB */
667     sic22 += sic22LSB & 0x00FF;
668     mpl115_coeffC22 = (double) (sic22);
669     mpl115_coeffC22 /= 32.0; //16-11=5
670     mpl115_coeffC22 /= 33554432.0;          /* 10+15=25 fract */
671
672     DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf",
673           mpl115_coeffA0, 
674           mpl115_coeffB1, 
675           mpl115_coeffB2, 
676           mpl115_coeffC12, 
677           mpl115_coeffC11, 
678           mpl115_coeffC22);
679     return 0;
680 }
681
682
683 /**
684  * Convert raw adc values to real data using the sensor coefficients.
685  *
686  * @param adc_pressure adc pressure value to be converted
687  * @param adc_temp     adc temperature value to be converted
688  * @param pressure     computed real pressure
689  * @param temperature  computed real temperature
690  */
691 static void MPL115_convert_adc_to_real(double   adc_pressure,
692                                        double   adc_temp,
693                                        double * pressure,
694                                        double * temperature)
695 {
696     double Pcomp;
697     Pcomp = mpl115_coeffA0 +                                            \
698         (mpl115_coeffB1 + mpl115_coeffC11*adc_pressure + mpl115_coeffC12*adc_temp) * adc_pressure + \
699         (mpl115_coeffB2 + mpl115_coeffC22*adc_temp) * adc_temp;
700     
701     *pressure = ((1150.0-500.0) * Pcomp / 1023.0) + 500.0;
702     *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
703     DEBUG ("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C",
704            *pressure,
705            *temperature);
706 }
707
708
709 /** 
710  * Read sensor averegaed measurements
711  *
712  * @param pressure    averaged measured pressure
713  * @param temperature averaged measured temperature
714  *
715  * @return Zero when successful
716  */
717 static int MPL115_read_averaged(double * pressure, double * temperature)
718 {
719     uint8_t mpl115_conv[MPL115_NUM_CONV]; 
720     int8_t  res;
721     int     retries;
722     int     conv_pressure;
723     int     conv_temperature;
724     double  adc_pressure;
725     double  adc_temperature;
726     char    errbuf[1024];
727
728     *pressure    = 0.0;
729     *temperature = 0.0;
730    
731     /* start conversion of both temp and presure */
732     retries = MPL115_CONVERSION_RETRIES;
733     while (retries>0)
734     {
735         /* write 1 to start conversion */
736         res = i2c_smbus_write_byte_data (i2c_bus_fd,
737                                          MPL115_CMD_CONVERT_BOTH,
738                                          0x01);
739         if (res >= 0)
740             break;
741
742         --retries;
743         if(retries>0)
744         {
745             ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, " \
746                    "will retry at most %d more times",
747                    sstrerror (errno, errbuf, sizeof (errbuf)),
748                    retries);
749         }
750         else
751         {
752             ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, "\
753                    "too many failed retries",
754                    sstrerror (errno, errbuf, sizeof (errbuf)));
755             return -1;
756         }
757     }
758
759     usleep (10000); /* wait 10ms for the conversion */
760
761     retries=MPL115_CONVERSION_RETRIES;
762     while (retries>0)
763     {
764         res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
765                                             MPL115_ADDR_CONV,
766                                             MPL115_NUM_CONV,
767                                             mpl115_conv); 
768         if (res >= 0)
769             break;
770
771         --retries;
772         if (retries>0)
773         {
774             ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \
775                    "will retry at most %d more times",
776                    sstrerror (errno, errbuf, sizeof (errbuf)),
777                    retries);
778         }
779         else
780         {
781             ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \
782                    "too many failed retries",
783                    sstrerror (errno, errbuf, sizeof (errbuf)));
784             return -1;
785         }
786     }
787     
788     conv_pressure    = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
789     conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
790     DEBUG ("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " \
791            "raw temperature ADC value = %d",
792            conv_pressure,
793            conv_temperature);
794
795     adc_pressure    = averaging_add_sample (&pressure_averaging, conv_pressure);
796     adc_temperature = averaging_add_sample (&temperature_averaging, conv_temperature);
797
798     MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature);
799
800     DEBUG ("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / temperature = %lf, " \
801            "real pressure = %lf hPa / temperature = %lf C",
802            adc_pressure,
803            adc_temperature,
804            *pressure,
805            *temperature);
806     
807     return 0;
808 }
809
810 /* ------------------------ MPL3115 access ------------------------ */
811
812 /** 
813  * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
814  *
815  * As a sideeffect will leave set I2C slave address.
816  * 
817  * @return 1 if MPL3115, 0 otherwise
818  */
819 static int MPL3115_detect(void)
820 {
821     __s32 res;
822     char errbuf[1024];
823
824     if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0)
825     {
826         ERROR("barometer: MPL3115_detect problem setting i2c slave address to 0x%02X: %s",
827               MPL3115_I2C_ADDRESS,
828               sstrerror (errno, errbuf, sizeof (errbuf)));
829         return 0 ;
830     }
831
832     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
833     if(res == MPL3115_WHO_AM_I_RESP)
834     {
835         DEBUG ("barometer: MPL3115_detect - positive detection");
836         return 1;
837     }
838
839     DEBUG ("barometer: MPL3115_detect - negative detection");
840     return 0;
841 }
842
843 /** 
844  * Adjusts oversampling to values supported by MPL3115
845  *
846  * MPL3115 supports only power of 2 in the range 1 to 128. 
847  */
848 static void MPL3115_adjust_oversampling(void)
849 {
850     int new_val = 0;
851
852     if(config_oversample > 100)
853     {
854         new_val = 128;
855         mpl3115_oversample = MPL3115_CTRL_REG1_OST_128;
856     }
857     else if(config_oversample > 48)
858     {
859         new_val = 64;
860         mpl3115_oversample = MPL3115_CTRL_REG1_OST_64;
861     }
862     else if(config_oversample > 24)
863     {
864         new_val = 32;
865         mpl3115_oversample = MPL3115_CTRL_REG1_OST_32;
866     }
867     else if(config_oversample > 12)
868     {
869         new_val = 16;
870         mpl3115_oversample = MPL3115_CTRL_REG1_OST_16;
871     }
872     else if(config_oversample > 6)
873     {
874         new_val = 8;
875         mpl3115_oversample = MPL3115_CTRL_REG1_OST_8;
876     }
877     else if(config_oversample > 3)
878     {
879         new_val = 4;
880         mpl3115_oversample = MPL3115_CTRL_REG1_OST_4;
881     }
882     else if(config_oversample > 1)
883     {
884         new_val = 2;
885         mpl3115_oversample = MPL3115_CTRL_REG1_OST_2;
886     }
887     else
888     {
889         new_val = 1;
890         mpl3115_oversample = MPL3115_CTRL_REG1_OST_1;
891     }
892
893     DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from %d to %d",
894           config_oversample, 
895           new_val);
896     config_oversample = new_val;
897 }
898
899 /** 
900  * Read sensor averegaed measurements
901  *
902  * @param pressure    averaged measured pressure
903  * @param temperature averaged measured temperature
904  *
905  * @return Zero when successful
906  */
907 static int MPL3115_read(double * pressure, double * temperature)
908 {
909     __s32 res;
910     __s32 ctrl ;
911     __u8 data[MPL3115_NUM_CONV_VALS];
912     long int tmp_value = 0;
913     char errbuf[1024];
914     
915     /* Set Active - activate the device from standby */
916     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
917     if (res < 0)
918     {
919         ERROR ("barometer: MPL3115_read - cannot read CTRL_REG1: %s",
920                sstrerror (errno, errbuf, sizeof (errbuf)));
921         return 1;
922     }
923     ctrl = res;
924     res = i2c_smbus_write_byte_data(i2c_bus_fd, 
925                                     MPL3115_REG_CTRL_REG1, 
926                                     ctrl | MPL3115_CTRL_REG1_SBYB);
927     if (res < 0)
928     {
929         ERROR ("barometer: MPL3115_read - problem activating: %s",
930                sstrerror (errno, errbuf, sizeof (errbuf)));
931         return 1;
932     }
933     
934     /* base sleep is 5ms x OST */
935     usleep(5000 * config_oversample);
936       
937     /* check the flags/status if ready */
938     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
939     if (res < 0)
940     {
941         ERROR ("barometer: MPL3115_read - cannot read status register: %s",
942                sstrerror (errno, errbuf, sizeof (errbuf)));
943         return 1;
944     }
945     
946     while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR)
947     {
948         /* try some extra sleep... */
949         usleep(10000);
950         
951         /* ... and repeat the check. The conversion has to finish sooner or later. */
952         res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
953         if (res < 0)
954         {
955             ERROR ("barometer: MPL3115_read - cannot read status register: %s",
956                    sstrerror (errno, errbuf, sizeof (errbuf)));
957             return 1;
958         }
959     }
960     
961     /* Now read all the data in one block. There is address autoincrement. */
962     res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
963                                         MPL3115_REG_OUT_P_MSB, 
964                                         MPL3115_NUM_CONV_VALS,
965                                         data);
966     if (res < 0)
967     {
968         ERROR ("barometer: MPL3115_read - cannot read data registers: %s",
969                sstrerror (errno, errbuf, sizeof (errbuf)));
970         return 1;
971     }
972     
973     tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
974     *pressure = ((double) tmp_value) / 4.0 / 16.0 / 100.0;
975     DEBUG ("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
976     
977     if(data[3] > 0x7F)
978     {
979         data[3] = ~data[3] + 1;
980         *temperature = data[3];
981         *temperature = - *temperature;
982     }
983     else
984     {
985         *temperature = data[3];
986     }
987     
988     *temperature += (double)(data[4]) / 256.0;
989     DEBUG ("barometer: MPL3115_read - temperature = %lf C", *temperature);
990     
991     return 0;
992 }
993
994 /** 
995  * Initialize MPL3115 for barometeric measurements
996  * 
997  * @return 0 if successful
998  */
999 static int MPL3115_init_sensor(void)
1000 {
1001     __s32 res;
1002     __s8 offset;
1003     char errbuf[1024];
1004     
1005     /* Reset the sensor. It will reset immediately without ACKing */
1006     /* the transaction, so no error handling here. */
1007     i2c_smbus_write_byte_data(i2c_bus_fd, 
1008                               MPL3115_REG_CTRL_REG1, 
1009                               MPL3115_CTRL_REG1_RST);
1010     
1011     /* wait some time for the reset to finish */
1012     usleep(100000);
1013
1014     /* now it should be in standby already so we can go and configure it */
1015     
1016     /*  Set temperature offset. */
1017     /*  result = ADCtemp + offset [C] */
1018     offset = (__s8) (config_temp_offset * 16.0);
1019     res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset);
1020     if (res < 0)
1021     {
1022         ERROR ("barometer: MPL3115_init_sensor - problem setting temp offset: %s",
1023                sstrerror (errno, errbuf, sizeof (errbuf)));
1024         return -1;
1025     }
1026     
1027     /*  Set pressure offset. */
1028     /*  result = ADCpress + offset [hPa] */
1029     offset = (__s8) (config_press_offset * 100.0 / 4.0);
1030     res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset);
1031     if (res < 0)
1032     {
1033         ERROR ("barometer: MPL3115_init_sensor - problem setting pressure offset: %s",
1034                sstrerror (errno, errbuf, sizeof (errbuf)));
1035         return -1;
1036     }
1037
1038     /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
1039     res = i2c_smbus_write_byte_data(i2c_bus_fd, 
1040                                     MPL3115_REG_PT_DATA_CFG,
1041                                     MPL3115_PT_DATA_DREM        \
1042                                     | MPL3115_PT_DATA_PDEF      \
1043                                     | MPL3115_PT_DATA_TDEF);
1044     if (res < 0)
1045     {
1046         ERROR ("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s",
1047                sstrerror (errno, errbuf, sizeof (errbuf)));
1048         return -1;
1049     }
1050
1051     /* Set to barometer with an OSR */ 
1052     res = i2c_smbus_write_byte_data(i2c_bus_fd, 
1053                                     MPL3115_REG_CTRL_REG1, 
1054                                     mpl3115_oversample);
1055     if (res < 0)
1056     {
1057         ERROR ("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
1058                sstrerror (errno, errbuf, sizeof (errbuf)));
1059         return -1;
1060     }
1061
1062     return 0;
1063 }
1064
1065 /* ------------------------ BMP085 access ------------------------ */
1066
1067 /** 
1068  * Detect presence of a BMP085 pressure sensor by checking its ID register
1069  *
1070  * As a sideeffect will leave set I2C slave address.
1071  * 
1072  * @return 1 if BMP085, 0 otherwise
1073  */
1074 static int BMP085_detect(void)
1075 {
1076     __s32 res;
1077     char errbuf[1024];
1078
1079     if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0)
1080     {
1081         ERROR("barometer: BMP085_detect - problem setting i2c slave address to 0x%02X: %s",
1082               BMP085_I2C_ADDRESS,
1083               sstrerror (errno, errbuf, sizeof (errbuf)));
1084         return 0 ;
1085     }
1086
1087     res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG);
1088     if(res == BMP085_CHIP_ID)
1089     {
1090         DEBUG ("barometer: BMP085_detect - positive detection");
1091
1092         /* get version */
1093         res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION );
1094         if (res < 0)
1095         {
1096             ERROR("barometer: BMP085_detect - problem checking chip version: %s",
1097                   sstrerror (errno, errbuf, sizeof (errbuf)));
1098             return 0 ;
1099         }
1100         DEBUG ("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X",
1101                res & 0x0f,
1102                (res & 0xf0) >> 4);
1103         return 1;
1104     }
1105
1106     DEBUG ("barometer: BMP085_detect - negative detection");
1107     return 0;
1108 }
1109
1110
1111 /** 
1112  * Adjusts oversampling settings to values supported by BMP085
1113  *
1114  * BMP085 supports only 1,2,4 or 8 samples. 
1115  */
1116 static void BMP085_adjust_oversampling(void)
1117 {
1118     int new_val = 0;
1119
1120     if( config_oversample > 6 ) /* 8 */
1121     {
1122         new_val = 8;
1123         bmp085_oversampling = 3;
1124         bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3;
1125         bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3;
1126     }
1127     else if( config_oversample > 3 ) /* 4 */
1128     {
1129         new_val = 4;
1130         bmp085_oversampling = 2;
1131         bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2;
1132         bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2;
1133     }
1134     else if( config_oversample > 1 ) /* 2 */
1135     {
1136         new_val = 2;
1137         bmp085_oversampling = 1;
1138         bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1;
1139         bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1;
1140     }
1141     else /* 1 */
1142     {
1143         new_val = 1;
1144         bmp085_oversampling = 0;
1145         bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0;
1146         bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0;
1147     }
1148
1149     DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from %d to %d",
1150           config_oversample, 
1151           new_val);
1152     config_oversample = new_val;
1153 }
1154
1155
1156 /** 
1157  * Read the BMP085 sensor conversion coefficients.
1158  *
1159  * These are (device specific) constants so we can read them just once.
1160  *
1161  * @return Zero when successful
1162  */
1163 static int BMP085_read_coeffs(void)
1164 {
1165     __s32 res;
1166     __u8 coeffs[BMP085_NUM_COEFFS]; 
1167     char errbuf[1024];
1168
1169     res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
1170                                         BMP085_ADDR_COEFFS,
1171                                         BMP085_NUM_COEFFS, 
1172                                         coeffs);
1173     if (res < 0)
1174     {
1175         ERROR ("barometer: BMP085_read_coeffs - problem reading data: %s",
1176                sstrerror (errno, errbuf, sizeof (errbuf)));
1177         return -1;
1178     }
1179     
1180     bmp085_AC1 = ((int16_t)  coeffs[0]  <<8) | (int16_t)  coeffs[1];
1181     bmp085_AC2 = ((int16_t)  coeffs[2]  <<8) | (int16_t)  coeffs[3];
1182     bmp085_AC3 = ((int16_t)  coeffs[4]  <<8) | (int16_t)  coeffs[5];
1183     bmp085_AC4 = ((uint16_t) coeffs[6]  <<8) | (uint16_t) coeffs[7];
1184     bmp085_AC5 = ((uint16_t) coeffs[8]  <<8) | (uint16_t) coeffs[9];
1185     bmp085_AC6 = ((uint16_t) coeffs[10] <<8) | (uint16_t) coeffs[11];
1186     bmp085_B1 =  ((int16_t)  coeffs[12] <<8) | (int16_t)  coeffs[13];
1187     bmp085_B2 =  ((int16_t)  coeffs[14] <<8) | (int16_t)  coeffs[15];
1188     bmp085_MB =  ((int16_t)  coeffs[16] <<8) | (int16_t)  coeffs[17];
1189     bmp085_MC =  ((int16_t)  coeffs[18] <<8) | (int16_t)  coeffs[19];
1190     bmp085_MD =  ((int16_t)  coeffs[20] <<8) | (int16_t)  coeffs[21];
1191
1192     DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"\
1193           " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d",
1194           bmp085_AC1,
1195           bmp085_AC2,
1196           bmp085_AC3,
1197           bmp085_AC4,
1198           bmp085_AC5,
1199           bmp085_AC6,
1200           bmp085_B1,
1201           bmp085_B2,
1202           bmp085_MB,
1203           bmp085_MC,
1204           bmp085_MD);
1205
1206     return 0;
1207 }
1208
1209
1210 /**
1211  * Convert raw BMP085 adc values to real data using the sensor coefficients.
1212  *
1213  * @param adc_pressure adc pressure value to be converted
1214  * @param adc_temp     adc temperature value to be converted
1215  * @param pressure     computed real pressure
1216  * @param temperature  computed real temperature
1217  */
1218 static void BMP085_convert_adc_to_real(long adc_pressure,
1219                                        long adc_temperature,
1220                                        double * pressure,
1221                                        double * temperature)
1222
1223 {
1224     long X1, X2, X3;
1225     long B3, B5, B6;
1226     unsigned long B4, B7;
1227
1228     long T;
1229     long P;
1230
1231
1232     /* calculate real temperature */
1233     X1 = ( (adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15;
1234     X2 = (bmp085_MC << 11) / (X1 + bmp085_MD);
1235
1236     /* B5, T */
1237     B5 = X1 + X2;
1238     T = (B5 + 8) >> 4;
1239     *temperature = (double)T * 0.1;
1240
1241     /* calculate real pressure */
1242     /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept */
1243
1244     /* B6, B3 */
1245     B6 = B5 - 4000;
1246     X1 = ((bmp085_B2 * ((B6 * B6)>>12)) >> 11 );
1247     X2 = (((long)bmp085_AC2 * B6) >> 11);
1248     X3 = X1 + X2;
1249     B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
1250     
1251     /* B4 */
1252     X1 = (((long)bmp085_AC3*B6) >> 13);
1253     X2 = (bmp085_B1*((B6*B6) >> 12) ) >> 16;
1254     X3 = ((X1 + X2) + 2 ) >> 2;
1255     B4 = ((long)bmp085_AC4* (unsigned long)(X3 + 32768)) >> 15;
1256     
1257     /* B7, P */
1258     B7 =  (unsigned long)(adc_pressure - B3)*(50000>>bmp085_oversampling);
1259     if( B7 < 0x80000000 )
1260     {
1261         P = (B7 << 1) / B4;
1262     }
1263     else
1264     {
1265         P = (B7/B4) << 1;
1266     }
1267     X1 = (P >> 8) * (P >> 8);
1268     X1 = (X1 * 3038) >> 16;
1269     X2 = ((-7357) * P) >> 16;
1270     P = P + ( ( X1 + X2 + 3791 ) >> 4);
1271     
1272     *pressure = P / 100.0; // in [hPa] 
1273     DEBUG ("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C",
1274            *pressure,
1275            *temperature);
1276 }
1277
1278     
1279 /** 
1280  * Read compensated sensor measurements
1281  *
1282  * @param pressure    averaged measured pressure
1283  * @param temperature averaged measured temperature
1284  *
1285  * @return Zero when successful
1286  */
1287 static int BMP085_read(double * pressure, double * temperature)
1288 {
1289     __s32 res;
1290     __u8 measBuff[3];
1291
1292     long adc_pressure;
1293     long adc_temperature;
1294
1295     char errbuf[1024];
1296
1297     /* start conversion of temperature */
1298     res = i2c_smbus_write_byte_data( i2c_bus_fd,
1299                                      BMP085_ADDR_CTRL_REG,
1300                                      BMP085_CMD_CONVERT_TEMP );
1301     if (res < 0)
1302     {
1303         ERROR ("barometer: BMP085_read - problem requesting temperature conversion: %s",
1304                sstrerror (errno, errbuf, sizeof (errbuf)));
1305         return 1;
1306     }
1307
1308     usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
1309
1310     res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
1311                                          BMP085_ADDR_CONV, 
1312                                          2,
1313                                          measBuff); 
1314     if (res < 0)
1315     {
1316         ERROR ("barometer: BMP085_read - problem reading temperature data: %s",
1317                sstrerror (errno, errbuf, sizeof (errbuf)));
1318         return 1;
1319     }
1320
1321     adc_temperature = ( (unsigned short)measBuff[0] << 8 ) + measBuff[1]; 
1322     
1323
1324     /* get presure */
1325     res = i2c_smbus_write_byte_data( i2c_bus_fd,
1326                                      BMP085_ADDR_CTRL_REG, 
1327                                      bmp085_cmdCnvPress );
1328     if (res < 0)
1329     {
1330         ERROR ("barometer: BMP085_read - problem requesting pressure conversion: %s",
1331                sstrerror (errno, errbuf, sizeof (errbuf)));
1332         return 1;
1333     }
1334
1335     usleep(bmp085_timeCnvPress); /* wait for the conversion */
1336
1337     res = i2c_smbus_read_i2c_block_data( i2c_bus_fd,
1338                                          BMP085_ADDR_CONV, 
1339                                          3,
1340                                          measBuff );
1341     if (res < 0)
1342     {
1343         ERROR ("barometer: BMP085_read - problem reading pressure data: %s",
1344                sstrerror (errno, errbuf, sizeof (errbuf)));
1345         return 1;
1346     }
1347
1348     adc_pressure = (long)((((ulong)measBuff[0]<<16) | ((ulong)measBuff[1]<<8) | (ulong)measBuff[2] ) >> (8 - bmp085_oversampling));
1349     
1350
1351     DEBUG ("barometer: BMP085_read - raw pressure ADC value = %ld, " \
1352            "raw temperature ADC value = %ld",
1353            adc_pressure,
1354            adc_temperature);
1355
1356     BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature);
1357
1358     return 0;
1359 }
1360
1361
1362
1363 /* ------------------------ Sensor detection ------------------------ */
1364 /** 
1365  * Detect presence of a supported sensor.
1366  *
1367  * As a sideeffect will leave set I2C slave address.
1368  * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
1369  * first sensor beeing found.
1370  * 
1371  * @return detected sensor type
1372  */
1373 enum Sensor_type Detect_sensor_type(void)
1374 {
1375     if(BMP085_detect())
1376         return Sensor_BMP085;
1377
1378     else if(MPL3115_detect())
1379         return Sensor_MPL3115;
1380
1381     else if(MPL115_detect())
1382         return Sensor_MPL115;
1383
1384     return Sensor_none;
1385 }
1386
1387 /* ------------------------ Common functionality ------------------------ */
1388
1389 /**
1390  * Convert absolute pressure (in hPa) to mean sea level pressure
1391  *
1392  * Implemented methods are:
1393  * - MSLP_NONE - no converions, returns absolute pressure
1394  *
1395  * - MSLP_INTERNATIONAL - see http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
1396  *           Requires #config_altitude
1397  *
1398  * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See 
1399  *                http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
1400  *           Requires both #config_altitude and temperature reference(s).
1401  *
1402  * @param abs_pressure absloute pressure to be converted
1403  *
1404  * @return mean sea level pressure if successful, NAN otherwise
1405  */
1406 static double abs_to_mean_sea_level_pressure(double abs_pressure)
1407 {
1408     double mean = -1.0;
1409     double temp = 0.0;
1410     int result = 0;
1411
1412     if (config_normalize >= MSLP_DEU_WETT)
1413     {
1414         result = get_reference_temperature(&temp);
1415         if(result)
1416         {
1417             return NAN;
1418         }
1419     }
1420
1421     switch(config_normalize)
1422     {
1423     case MSLP_NONE:
1424         mean = abs_pressure;
1425         break;
1426         
1427     case MSLP_INTERNATIONAL:
1428         mean = abs_pressure / \
1429             pow(1.0 - 0.0065*config_altitude/288.15, 9.80665*0.0289644/(8.31447*0.0065));
1430         break;
1431         
1432     case MSLP_DEU_WETT:
1433     {
1434         double E; /* humidity */
1435         double x;
1436         if(temp<9.1)
1437             E = 5.6402 * (-0.0916 + exp(0.06*temp) );
1438         else
1439             E = 18.2194 * (1.0463 - exp(-0.0666*temp) );
1440         x = 9.80665 / (287.05 * (temp+273.15 + 0.12*E + 0.0065*config_altitude/2)) * config_altitude;
1441         mean = abs_pressure * exp(x);
1442     }
1443     break;
1444
1445     default:
1446         ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", 
1447                config_normalize);
1448         mean = abs_pressure;
1449         break;
1450     }
1451
1452     DEBUG ("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, method = %d, meanPressure = %lf hPa",
1453            abs_pressure,
1454            config_normalize,
1455            mean);
1456
1457     return mean; 
1458 }
1459
1460 /* ------------------------ main plugin callbacks ------------------------ */
1461
1462 /** 
1463  * Main plugin configuration callback (using simple config)
1464  * 
1465  * @param key   configuration key we should process
1466  * @param value configuration value we should process
1467  * 
1468  * @return Zero when successful.
1469  */
1470 static int collectd_barometer_config (const char *key, const char *value)
1471 {
1472     DEBUG("barometer: collectd_barometer_config");
1473
1474     if (strcasecmp (key, "Device") == 0)
1475     {
1476         sfree (config_device);
1477         config_device = strdup (value);
1478     }
1479     else if (strcasecmp (key, "Oversampling") == 0)
1480     {
1481         int oversampling_tmp = atoi (value);
1482         if (oversampling_tmp < 1 || oversampling_tmp > 1024)
1483         {
1484             WARNING ("barometer: collectd_barometer_config: invalid oversampling: %d." \
1485                      " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for MPL3115) or 1 to 8 (for BMP085).",
1486                      oversampling_tmp);
1487             return 1;
1488         }
1489         config_oversample = oversampling_tmp;
1490     }
1491     else if (strcasecmp (key, "Altitude") == 0)
1492     {
1493         config_altitude = atof (value);
1494     }
1495     else if (strcasecmp (key, "Normalization") == 0)
1496     {
1497         int normalize_tmp = atoi (value);
1498         if (normalize_tmp < 0 || normalize_tmp > 2)
1499         {
1500             WARNING ("barometer: collectd_barometer_config: invalid normalization: %d",
1501                      normalize_tmp);
1502             return 1;
1503         }
1504         config_normalize = normalize_tmp;
1505     }
1506     else if (strcasecmp (key, "TemperatureSensor") == 0)
1507     {
1508         if(temp_list_add(temp_list, value))
1509         {
1510             return -1;
1511         }
1512     }
1513     else if (strcasecmp (key, "PressureOffset") == 0)
1514     {
1515         config_press_offset = atof(value);
1516     }
1517     else if (strcasecmp (key, "TemperatureOffset") == 0)
1518     {
1519         config_temp_offset = atof(value);
1520     }
1521     else 
1522     {
1523         return -1;
1524     }
1525
1526     return 0;
1527 }
1528
1529
1530 /** 
1531  * Shutdown callback.
1532  * 
1533  * Close I2C and delete all the buffers.
1534  * 
1535  * @return Zero when successful (at the moment the only possible outcome)
1536  */
1537 static int collectd_barometer_shutdown(void)
1538 {
1539     DEBUG ("barometer: collectd_barometer_shutdown");
1540
1541     if(sensor_type == Sensor_MPL115)
1542     {
1543         averaging_delete (&pressure_averaging);
1544         averaging_delete (&temperature_averaging);
1545
1546         temp_list_delete(&temp_list);
1547     }
1548
1549     if (i2c_bus_fd > 0)
1550     {
1551         close (i2c_bus_fd);
1552         i2c_bus_fd = -1;
1553         sfree (config_device);
1554     }
1555
1556     return 0;
1557 }
1558
1559
1560 /** 
1561  * Plugin read callback for MPL115.
1562  * 
1563  *  Dispatching will create values:
1564  *  - <hostname>/barometer-mpl115/pressure-normalized
1565  *  - <hostname>/barometer-mpl115/pressure-absolute
1566  *  - <hostname>/barometer-mpl115/temperature
1567  *
1568  * @return Zero when successful.
1569  */
1570 static int MPL115_collectd_barometer_read (void)
1571 {
1572     int result = 0;
1573
1574     double pressure        = 0.0;
1575     double temperature     = 0.0;
1576     double norm_pressure   = 0.0;
1577
1578     value_list_t vl = VALUE_LIST_INIT;
1579     value_t      values[1];
1580     
1581     DEBUG("barometer: MPL115_collectd_barometer_read");
1582
1583     if (!configured)
1584     {
1585         return -1;
1586     }
1587
1588     /* Rather than delaying init, we will intitialize during first read. This
1589        way at least we have a better chance to have the reference temperature
1590        already available. */
1591     if(!avg_initialized)
1592     {
1593         int i;
1594         for(i=0; i<config_oversample-1; ++i)
1595         {
1596             result = MPL115_read_averaged(&pressure, &temperature);
1597             if(result)
1598             {
1599                 ERROR ("barometer: MPL115_collectd_barometer_read - mpl115 read, ignored during init");
1600             }
1601             DEBUG("barometer: MPL115_collectd_barometer_read - init %d / %d", i+1, config_oversample-1);
1602             usleep(20000);
1603         }
1604         avg_initialized = 1;
1605     }
1606
1607     result = MPL115_read_averaged(&pressure, &temperature);
1608     if(result)
1609         return result;
1610
1611     norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1612
1613     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
1614     sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
1615     sstrncpy (vl.plugin_instance, "mpl115", sizeof (vl.plugin_instance));
1616
1617     vl.values_len = 1;
1618     vl.values = values;
1619
1620     /* dispatch normalized air pressure */
1621     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1622     sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
1623     values[0].gauge = norm_pressure;
1624     plugin_dispatch_values (&vl);
1625
1626     /* dispatch absolute air pressure */
1627     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1628     sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
1629     values[0].gauge = pressure;
1630     plugin_dispatch_values (&vl);
1631
1632     /* dispatch sensor temperature */
1633     sstrncpy (vl.type, "temperature", sizeof (vl.type));
1634     sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
1635     values[0].gauge = temperature;
1636     plugin_dispatch_values (&vl);
1637
1638     return 0;
1639 }
1640
1641
1642 /** 
1643  * Plugin read callback for MPL3115.
1644  * 
1645  *  Dispatching will create values:
1646  *  - <hostname>/barometer-mpl3115/pressure-normalized
1647  *  - <hostname>/barometer-mpl3115/pressure-absolute
1648  *  - <hostname>/barometer-mpl3115/temperature
1649  *
1650  * @return Zero when successful.
1651  */
1652 static int MPL3115_collectd_barometer_read (void)
1653 {
1654     int result = 0;
1655     
1656     double pressure        = 0.0;
1657     double temperature     = 0.0;
1658     double norm_pressure   = 0.0;
1659     
1660     value_list_t vl = VALUE_LIST_INIT;
1661     value_t      values[1];
1662     
1663     DEBUG("barometer: MPL3115_collectd_barometer_read");
1664     
1665     if (!configured)
1666     {
1667         return -1;
1668     }
1669     
1670     result = MPL3115_read(&pressure, &temperature);
1671     if(result)
1672         return result;
1673
1674     norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1675
1676     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
1677     sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
1678     sstrncpy (vl.plugin_instance, "mpl3115", sizeof (vl.plugin_instance));
1679
1680     vl.values_len = 1;
1681     vl.values = values;
1682
1683     /* dispatch normalized air pressure */
1684     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1685     sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
1686     values[0].gauge = norm_pressure;
1687     plugin_dispatch_values (&vl);
1688
1689     /* dispatch absolute air pressure */
1690     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1691     sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
1692     values[0].gauge = pressure;
1693     plugin_dispatch_values (&vl);
1694
1695     /* dispatch sensor temperature */
1696     sstrncpy (vl.type, "temperature", sizeof (vl.type));
1697     sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
1698     values[0].gauge = temperature;
1699     plugin_dispatch_values (&vl);
1700
1701     return 0;
1702 }
1703
1704
1705 /** 
1706  * Plugin read callback for BMP085.
1707  * 
1708  *  Dispatching will create values:
1709  *  - <hostname>/barometer-bmp085/pressure-normalized
1710  *  - <hostname>/barometer-bmp085/pressure-absolute
1711  *  - <hostname>/barometer-bmp085/temperature
1712  *
1713  * @return Zero when successful.
1714  */
1715 static int BMP085_collectd_barometer_read (void)
1716 {
1717     int result = 0;
1718     
1719     double pressure        = 0.0;
1720     double temperature     = 0.0;
1721     double norm_pressure   = 0.0;
1722     
1723     value_list_t vl = VALUE_LIST_INIT;
1724     value_t      values[1];
1725     
1726     DEBUG("barometer: BMP085_collectd_barometer_read");
1727     
1728     if (!configured)
1729     {
1730         return -1;
1731     }
1732     
1733     result = BMP085_read(&pressure, &temperature);
1734     if(result)
1735         return result;
1736
1737     norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1738
1739     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
1740     sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
1741     sstrncpy (vl.plugin_instance, "bmp085", sizeof (vl.plugin_instance));
1742
1743     vl.values_len = 1;
1744     vl.values = values;
1745
1746     /* dispatch normalized air pressure */
1747     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1748     sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
1749     values[0].gauge = norm_pressure;
1750     plugin_dispatch_values (&vl);
1751
1752     /* dispatch absolute air pressure */
1753     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1754     sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
1755     values[0].gauge = pressure;
1756     plugin_dispatch_values (&vl);
1757
1758     /* dispatch sensor temperature */
1759     sstrncpy (vl.type, "temperature", sizeof (vl.type));
1760     sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
1761     values[0].gauge = temperature;
1762     plugin_dispatch_values (&vl);
1763
1764     return 0;
1765 }
1766
1767
1768 /** 
1769  * Initialization callback
1770  * 
1771  * Check config, initialize I2C bus access, conversion coefficients and averaging
1772  * ring buffers
1773  * 
1774  * @return Zero when successful.
1775  */
1776 static int collectd_barometer_init (void)
1777 {
1778     char errbuf[1024];
1779
1780     DEBUG ("barometer: collectd_barometer_init");
1781
1782     if (config_device == NULL)
1783     {
1784         ERROR("barometer: collectd_barometer_init I2C bus device not configured");
1785         return -1;
1786     }
1787
1788     if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude))
1789     {
1790         ERROR("barometer: collectd_barometer_init no altitude configured " \
1791               "for mean sea level pressure normalization.");
1792         return -1;
1793     }
1794
1795     if (config_normalize == MSLP_DEU_WETT
1796         &&
1797         temp_list == NULL)
1798     {
1799         ERROR("barometer: collectd_barometer_init no temperature reference "\
1800               "configured for mean sea level pressure normalization.");
1801         return -1;
1802     }
1803
1804
1805     i2c_bus_fd = open(config_device, O_RDWR);
1806     if (i2c_bus_fd < 0)
1807     {
1808         ERROR ("barometer: collectd_barometer_init problem opening I2C bus device \"%s\": %s (is loaded mod i2c-dev?)",
1809                config_device,
1810                sstrerror (errno, errbuf, sizeof (errbuf)));
1811         return -1;
1812     }
1813
1814     /* detect sensor type - this will also set slave address */
1815     sensor_type = Detect_sensor_type();
1816
1817     /* init correct sensor type */
1818     switch(sensor_type)
1819     {
1820 /* MPL3115 */
1821     case Sensor_MPL3115:
1822     {
1823         MPL3115_adjust_oversampling();
1824         
1825         if(MPL3115_init_sensor())
1826             return -1;
1827         
1828         plugin_register_read ("barometer", MPL3115_collectd_barometer_read);
1829     }
1830     break;
1831
1832 /* MPL115 */
1833     case Sensor_MPL115:
1834     {
1835         if (averaging_create (&pressure_averaging, config_oversample))
1836         {
1837             ERROR("barometer: collectd_barometer_init pressure averaging init failed");
1838             return -1;
1839         }
1840         
1841         if (averaging_create (&temperature_averaging, config_oversample))
1842         {
1843             ERROR("barometer: collectd_barometer_init temperature averaging init failed");
1844             return -1;
1845         }
1846         
1847         if (MPL115_read_coeffs() < 0)
1848             return -1;
1849         
1850         plugin_register_read ("barometer", MPL115_collectd_barometer_read);
1851     }
1852     break;
1853
1854 /* BMP085 */
1855     case Sensor_BMP085:
1856     {
1857         BMP085_adjust_oversampling();
1858
1859         if (BMP085_read_coeffs() < 0)
1860             return -1;
1861
1862         plugin_register_read ("barometer", BMP085_collectd_barometer_read);
1863     }
1864     break;
1865
1866 /* anything else -> error */
1867     default:
1868         ERROR("barometer: collectd_barometer_init - no supported sensor found");
1869         return -1;
1870     }
1871         
1872
1873     configured = 1;
1874     return 0;
1875 }
1876
1877 /* ------------------------ plugin register / entry point ------------------------ */
1878
1879 /** 
1880  * Plugin "entry" - register all callback.
1881  * 
1882  */
1883 void module_register (void)
1884 {
1885     plugin_register_config ("barometer", 
1886                             collectd_barometer_config, 
1887                             config_keys, 
1888                             config_keys_num);
1889     plugin_register_init ("barometer", collectd_barometer_init);
1890     plugin_register_shutdown ("barometer", collectd_barometer_shutdown);
1891 }