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