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