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