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