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