Replace zu with PRIu64 and llu with new macro, PRIsz, which will make it easier to...
[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("barometer: get_reference_temperature - initialize \"%s\", %" PRIsz
416             " 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 %" PRIsz ": %lf **",
424               i, 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 %" PRIsz ": %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 %" PRIsz
468               ": %lf **",
469               i, values[i]);
470         if (!isnan(values[i])) {
471           avg_sum += values[i];
472           ++avg_num;
473         }
474       }
475       free(values);
476       values = NULL;
477     }
478
479     if (avg_num == 0) {
480       ERROR("barometer: get_reference_temperature - could not read \"%s\"",
481             list->sensor_name);
482       list->initialized = 0;
483       list->num_values = 0;
484     } else {
485       average = avg_sum / (double)avg_num;
486       if (isnan(*result))
487         *result = average;
488       else if (*result > average)
489         *result = average;
490     }
491     list = list->next;
492   } /* while sensor list */
493
494   if (*result == NAN) {
495     ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
496     return -1;
497   }
498   DEBUG("barometer: get_reference_temperature - temp is %lf", *result);
499   return 0;
500 }
501
502 /* ------------------------ MPL115 access ------------------------ */
503
504 /**
505  * Detect presence of a MPL115 pressure sensor.
506  *
507  * Unfortunately there seems to be no ID register so we just try to read first
508  * conversion coefficient from device at MPL115 address and hope it is really
509  * MPL115. We should use this check as the last resort (which would be the
510  * typical
511  * case anyway since MPL115 is the least accurate sensor).
512  * As a sideeffect will leave set I2C slave address.
513  *
514  * @return 1 if MPL115, 0 otherwise
515  */
516 static int MPL115_detect(void) {
517   __s32 res;
518   char errbuf[1024];
519
520   if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0) {
521     ERROR("barometer: MPL115_detect problem setting i2c slave address to "
522           "0x%02X: %s",
523           MPL115_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf)));
524     return 0;
525   }
526
527   res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL115_ADDR_COEFFS);
528   if (res >= 0) {
529     DEBUG("barometer: MPL115_detect - positive detection");
530     return 1;
531   }
532
533   DEBUG("barometer: MPL115_detect - negative detection");
534   return 0;
535 }
536
537 /**
538  * Read the MPL115 sensor conversion coefficients.
539  *
540  * These are (device specific) constants so we can read them just once.
541  *
542  * @return Zero when successful
543  */
544 static int MPL115_read_coeffs(void) {
545   uint8_t mpl115_coeffs[MPL115_NUM_COEFFS] = {0};
546   int32_t res;
547
548   int8_t sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
549   int8_t sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
550   int16_t sia0, sib1, sib2, sic12, sic11, sic22;
551
552   char errbuf[1024];
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",
559           sstrerror(errno, errbuf, sizeof(errbuf)));
560     return -1;
561   }
562
563   /* Using perhaps less elegant/efficient code, but more readable. */
564   /* a0: 16total 1sign 12int 4fract 0pad */
565   sia0MSB = mpl115_coeffs[0];
566   sia0LSB = mpl115_coeffs[1];
567   sia0 = (int16_t)sia0MSB << 8;      /* s16 type, Shift to MSB */
568   sia0 += (int16_t)sia0LSB & 0x00FF; /* Add LSB to 16bit number */
569   mpl115_coeffA0 = (double)(sia0);
570   mpl115_coeffA0 /= 8.0; /* 3 fract bits */
571
572   /* b1: 16total 1sign 2int 13fract 0pad */
573   sib1MSB = mpl115_coeffs[2];
574   sib1LSB = mpl115_coeffs[3];
575   sib1 = sib1MSB << 8;      /* Shift to MSB */
576   sib1 += sib1LSB & 0x00FF; /* Add LSB to 16bit number */
577   mpl115_coeffB1 = (double)(sib1);
578   mpl115_coeffB1 /= 8192.0; /* 13 fract */
579
580   /* b2: 16total 1sign 1int 14fract 0pad */
581   sib2MSB = mpl115_coeffs[4];
582   sib2LSB = mpl115_coeffs[5];
583   sib2 = sib2MSB << 8;      /* Shift to MSB */
584   sib2 += sib2LSB & 0x00FF; /* Add LSB to 16bit number */
585   mpl115_coeffB2 = (double)(sib2);
586   mpl115_coeffB2 /= 16384.0; /* 14 fract */
587
588   /* c12: 14total 1sign 0int 13fract 9pad */
589   sic12MSB = mpl115_coeffs[6];
590   sic12LSB = mpl115_coeffs[7];
591   sic12 = sic12MSB << 8; /* Shift to MSB only by 8 for MSB */
592   sic12 += sic12LSB & 0x00FF;
593   mpl115_coeffC12 = (double)(sic12);
594   mpl115_coeffC12 /= 4.0;       /* 16-14=2 */
595   mpl115_coeffC12 /= 4194304.0; /* 13+9=22 fract */
596
597   /* c11: 11total 1sign 0int 11fract 11pad */
598   sic11MSB = mpl115_coeffs[8];
599   sic11LSB = mpl115_coeffs[9];
600   sic11 = sic11MSB << 8; /* Shift to MSB only by 8 for MSB */
601   sic11 += sic11LSB & 0x00FF;
602   mpl115_coeffC11 = (double)(sic11);
603   mpl115_coeffC11 /= 32.0;      /* 16-11=5 */
604   mpl115_coeffC11 /= 4194304.0; /* 11+11=22 fract */
605
606   /* c12: 11total 1sign 0int 10fract 15pad */
607   sic22MSB = mpl115_coeffs[10];
608   sic22LSB = mpl115_coeffs[11];
609   sic22 = sic22MSB << 8; /* Shift to MSB only by 8 for MSB */
610   sic22 += sic22LSB & 0x00FF;
611   mpl115_coeffC22 = (double)(sic22);
612   mpl115_coeffC22 /= 32.0;       // 16-11=5
613   mpl115_coeffC22 /= 33554432.0; /* 10+15=25 fract */
614
615   DEBUG("barometer: MPL115_read_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, "
616         "c11=%lf, c22=%lf",
617         mpl115_coeffA0, mpl115_coeffB1, mpl115_coeffB2, mpl115_coeffC12,
618         mpl115_coeffC11, mpl115_coeffC22);
619   return 0;
620 }
621
622 /**
623  * Convert raw adc values to real data using the sensor coefficients.
624  *
625  * @param adc_pressure adc pressure value to be converted
626  * @param adc_temp     adc temperature value to be converted
627  * @param pressure     computed real pressure
628  * @param temperature  computed real temperature
629  */
630 static void MPL115_convert_adc_to_real(double adc_pressure, double adc_temp,
631                                        double *pressure, double *temperature) {
632   double Pcomp;
633   Pcomp = mpl115_coeffA0 +
634           (mpl115_coeffB1 + mpl115_coeffC11 * adc_pressure +
635            mpl115_coeffC12 * adc_temp) *
636               adc_pressure +
637           (mpl115_coeffB2 + mpl115_coeffC22 * adc_temp) * adc_temp;
638
639   *pressure = ((1150.0 - 500.0) * Pcomp / 1023.0) + 500.0;
640   *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
641   DEBUG("barometer: MPL115_convert_adc_to_real - got %lf hPa, %lf C", *pressure,
642         *temperature);
643 }
644
645 /**
646  * Read sensor averegaed measurements
647  *
648  * @param pressure    averaged measured pressure
649  * @param temperature averaged measured temperature
650  *
651  * @return Zero when successful
652  */
653 static int MPL115_read_averaged(double *pressure, double *temperature) {
654   uint8_t mpl115_conv[MPL115_NUM_CONV] = {0};
655   int8_t res;
656   int retries;
657   int conv_pressure;
658   int conv_temperature;
659   double adc_pressure;
660   double adc_temperature;
661   char errbuf[1024];
662
663   *pressure = 0.0;
664   *temperature = 0.0;
665
666   /* start conversion of both temp and presure */
667   retries = MPL115_CONVERSION_RETRIES;
668   while (retries > 0) {
669     /* write 1 to start conversion */
670     res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL115_CMD_CONVERT_BOTH, 0x01);
671     if (res >= 0)
672       break;
673
674     --retries;
675     if (retries > 0) {
676       ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, "
677             "will retry at most %d more times",
678             sstrerror(errno, errbuf, sizeof(errbuf)), retries);
679     } else {
680       ERROR("barometer: MPL115_read_averaged - requesting conversion: %s, "
681             "too many failed retries",
682             sstrerror(errno, errbuf, sizeof(errbuf)));
683       return -1;
684     }
685   }
686
687   usleep(10000); /* wait 10ms for the conversion */
688
689   retries = MPL115_CONVERSION_RETRIES;
690   while (retries > 0) {
691     res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL115_ADDR_CONV,
692                                         STATIC_ARRAY_SIZE(mpl115_conv),
693                                         mpl115_conv);
694     if (res >= 0)
695       break;
696
697     --retries;
698     if (retries > 0) {
699       ERROR("barometer: MPL115_read_averaged - reading conversion: %s, "
700             "will retry at most %d more times",
701             sstrerror(errno, errbuf, sizeof(errbuf)), retries);
702     } else {
703       ERROR("barometer: MPL115_read_averaged - reading conversion: %s, "
704             "too many failed retries",
705             sstrerror(errno, errbuf, sizeof(errbuf)));
706       return -1;
707     }
708   }
709
710   conv_pressure = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
711   conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
712   DEBUG("barometer: MPL115_read_averaged, raw pressure ADC value = %d, "
713         "raw temperature ADC value = %d",
714         conv_pressure, conv_temperature);
715
716   adc_pressure = averaging_add_sample(&pressure_averaging, conv_pressure);
717   adc_temperature =
718       averaging_add_sample(&temperature_averaging, conv_temperature);
719
720   MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure,
721                              temperature);
722
723   DEBUG("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / "
724         "temperature = %lf, "
725         "real pressure = %lf hPa / temperature = %lf C",
726         adc_pressure, adc_temperature, *pressure, *temperature);
727
728   return 0;
729 }
730
731 /* ------------------------ MPL3115 access ------------------------ */
732
733 /**
734  * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
735  *
736  * As a sideeffect will leave set I2C slave address.
737  *
738  * @return 1 if MPL3115, 0 otherwise
739  */
740 static int MPL3115_detect(void) {
741   __s32 res;
742   char errbuf[1024];
743
744   if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL3115_I2C_ADDRESS) < 0) {
745     ERROR("barometer: MPL3115_detect problem setting i2c slave address to "
746           "0x%02X: %s",
747           MPL3115_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf)));
748     return 0;
749   }
750
751   res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
752   if (res == MPL3115_WHO_AM_I_RESP) {
753     DEBUG("barometer: MPL3115_detect - positive detection");
754     return 1;
755   }
756
757   DEBUG("barometer: MPL3115_detect - negative detection");
758   return 0;
759 }
760
761 /**
762  * Adjusts oversampling to values supported by MPL3115
763  *
764  * MPL3115 supports only power of 2 in the range 1 to 128.
765  */
766 static void MPL3115_adjust_oversampling(void) {
767   int new_val = 0;
768
769   if (config_oversample > 100) {
770     new_val = 128;
771     mpl3115_oversample = MPL3115_CTRL_REG1_OST_128;
772   } else if (config_oversample > 48) {
773     new_val = 64;
774     mpl3115_oversample = MPL3115_CTRL_REG1_OST_64;
775   } else if (config_oversample > 24) {
776     new_val = 32;
777     mpl3115_oversample = MPL3115_CTRL_REG1_OST_32;
778   } else if (config_oversample > 12) {
779     new_val = 16;
780     mpl3115_oversample = MPL3115_CTRL_REG1_OST_16;
781   } else if (config_oversample > 6) {
782     new_val = 8;
783     mpl3115_oversample = MPL3115_CTRL_REG1_OST_8;
784   } else if (config_oversample > 3) {
785     new_val = 4;
786     mpl3115_oversample = MPL3115_CTRL_REG1_OST_4;
787   } else if (config_oversample > 1) {
788     new_val = 2;
789     mpl3115_oversample = MPL3115_CTRL_REG1_OST_2;
790   } else {
791     new_val = 1;
792     mpl3115_oversample = MPL3115_CTRL_REG1_OST_1;
793   }
794
795   DEBUG("barometer: MPL3115_adjust_oversampling - correcting oversampling from "
796         "%d to %d",
797         config_oversample, new_val);
798   config_oversample = new_val;
799 }
800
801 /**
802  * Read sensor averaged measurements
803  *
804  * @param pressure    averaged measured pressure
805  * @param temperature averaged measured temperature
806  *
807  * @return Zero when successful
808  */
809 static int MPL3115_read(double *pressure, double *temperature) {
810   __s32 res;
811   __s32 ctrl;
812   __u8 data[MPL3115_NUM_CONV_VALS];
813   long int tmp_value = 0;
814   char errbuf[1024];
815
816   /* Set Active - activate the device from standby */
817   res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
818   if (res < 0) {
819     ERROR("barometer: MPL3115_read - cannot read CTRL_REG1: %s",
820           sstrerror(errno, errbuf, sizeof(errbuf)));
821     return 1;
822   }
823   ctrl = res;
824   res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
825                                   ctrl | MPL3115_CTRL_REG1_SBYB);
826   if (res < 0) {
827     ERROR("barometer: MPL3115_read - problem activating: %s",
828           sstrerror(errno, errbuf, sizeof(errbuf)));
829     return 1;
830   }
831
832   /* base sleep is 5ms x OST */
833   usleep(5000 * config_oversample);
834
835   /* check the flags/status if ready */
836   res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
837   if (res < 0) {
838     ERROR("barometer: MPL3115_read - cannot read status register: %s",
839           sstrerror(errno, errbuf, sizeof(errbuf)));
840     return 1;
841   }
842
843   while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR) {
844     /* try some extra sleep... */
845     usleep(10000);
846
847     /* ... and repeat the check. The conversion has to finish sooner or later.
848      */
849     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
850     if (res < 0) {
851       ERROR("barometer: MPL3115_read - cannot read status register: %s",
852             sstrerror(errno, errbuf, sizeof(errbuf)));
853       return 1;
854     }
855   }
856
857   /* Now read all the data in one block. There is address autoincrement. */
858   res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, MPL3115_REG_OUT_P_MSB,
859                                       MPL3115_NUM_CONV_VALS, data);
860   if (res < 0) {
861     ERROR("barometer: MPL3115_read - cannot read data registers: %s",
862           sstrerror(errno, errbuf, sizeof(errbuf)));
863     return 1;
864   }
865
866   tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
867   *pressure = ((double)tmp_value) / 4.0 / 16.0 / 100.0;
868   DEBUG("barometer: MPL3115_read - absolute pressure = %lf hPa", *pressure);
869
870   if (data[3] > 0x7F) {
871     data[3] = ~data[3] + 1;
872     *temperature = data[3];
873     *temperature = -*temperature;
874   } else {
875     *temperature = data[3];
876   }
877
878   *temperature += (double)(data[4]) / 256.0;
879   DEBUG("barometer: MPL3115_read - temperature = %lf C", *temperature);
880
881   return 0;
882 }
883
884 /**
885  * Initialize MPL3115 for barometeric measurements
886  *
887  * @return 0 if successful
888  */
889 static int MPL3115_init_sensor(void) {
890   __s32 res;
891   __s8 offset;
892   char errbuf[1024];
893
894   /* Reset the sensor. It will reset immediately without ACKing */
895   /* the transaction, so no error handling here. */
896   i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
897                             MPL3115_CTRL_REG1_RST);
898
899   /* wait some time for the reset to finish */
900   usleep(100000);
901
902   /* now it should be in standby already so we can go and configure it */
903
904   /*  Set temperature offset. */
905   /*  result = ADCtemp + offset [C] */
906   offset = (__s8)(config_temp_offset * 16.0);
907   res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset);
908   if (res < 0) {
909     ERROR("barometer: MPL3115_init_sensor - problem setting temp offset: %s",
910           sstrerror(errno, errbuf, sizeof(errbuf)));
911     return -1;
912   }
913
914   /*  Set pressure offset. */
915   /*  result = ADCpress + offset [hPa] */
916   offset = (__s8)(config_press_offset * 100.0 / 4.0);
917   res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_P, offset);
918   if (res < 0) {
919     ERROR(
920         "barometer: MPL3115_init_sensor - problem setting pressure offset: %s",
921         sstrerror(errno, errbuf, sizeof(errbuf)));
922     return -1;
923   }
924
925   /* Enable Data Flags in PT_DATA_CFG - flags on both pressure and temp */
926   res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_PT_DATA_CFG,
927                                   MPL3115_PT_DATA_DREM | MPL3115_PT_DATA_PDEF |
928                                       MPL3115_PT_DATA_TDEF);
929   if (res < 0) {
930     ERROR("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s",
931           sstrerror(errno, errbuf, sizeof(errbuf)));
932     return -1;
933   }
934
935   /* Set to barometer with an OSR */
936   res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1,
937                                   mpl3115_oversample);
938   if (res < 0) {
939     ERROR("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
940           sstrerror(errno, errbuf, sizeof(errbuf)));
941     return -1;
942   }
943
944   return 0;
945 }
946
947 /* ------------------------ BMP085 access ------------------------ */
948
949 /**
950  * Detect presence of a BMP085 pressure sensor by checking its ID register
951  *
952  * As a sideeffect will leave set I2C slave address.
953  *
954  * @return 1 if BMP085, 0 otherwise
955  */
956 static int BMP085_detect(void) {
957   __s32 res;
958   char errbuf[1024];
959
960   if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, BMP085_I2C_ADDRESS) < 0) {
961     ERROR("barometer: BMP085_detect - problem setting i2c slave address to "
962           "0x%02X: %s",
963           BMP085_I2C_ADDRESS, sstrerror(errno, errbuf, sizeof(errbuf)));
964     return 0;
965   }
966
967   res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_ID_REG);
968   if (res == BMP085_CHIP_ID) {
969     DEBUG("barometer: BMP085_detect - positive detection");
970
971     /* get version */
972     res = i2c_smbus_read_byte_data(i2c_bus_fd, BMP085_ADDR_VERSION);
973     if (res < 0) {
974       ERROR("barometer: BMP085_detect - problem checking chip version: %s",
975             sstrerror(errno, errbuf, sizeof(errbuf)));
976       return 0;
977     }
978     DEBUG("barometer: BMP085_detect - chip version ML:0x%02X AL:0x%02X",
979           res & 0x0f, (res & 0xf0) >> 4);
980     return 1;
981   }
982
983   DEBUG("barometer: BMP085_detect - negative detection");
984   return 0;
985 }
986
987 /**
988  * Adjusts oversampling settings to values supported by BMP085
989  *
990  * BMP085 supports only 1,2,4 or 8 samples.
991  */
992 static void BMP085_adjust_oversampling(void) {
993   int new_val = 0;
994
995   if (config_oversample > 6) /* 8 */
996   {
997     new_val = 8;
998     bmp085_oversampling = 3;
999     bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_3;
1000     bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_3;
1001   } else if (config_oversample > 3) /* 4 */
1002   {
1003     new_val = 4;
1004     bmp085_oversampling = 2;
1005     bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_2;
1006     bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_2;
1007   } else if (config_oversample > 1) /* 2 */
1008   {
1009     new_val = 2;
1010     bmp085_oversampling = 1;
1011     bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_1;
1012     bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_1;
1013   } else /* 1 */
1014   {
1015     new_val = 1;
1016     bmp085_oversampling = 0;
1017     bmp085_cmdCnvPress = BMP085_CMD_CONVERT_PRESS_0;
1018     bmp085_timeCnvPress = BMP085_TIME_CNV_PRESS_0;
1019   }
1020
1021   DEBUG("barometer: BMP085_adjust_oversampling - correcting oversampling from "
1022         "%d to %d",
1023         config_oversample, new_val);
1024   config_oversample = new_val;
1025 }
1026
1027 /**
1028  * Read the BMP085 sensor conversion coefficients.
1029  *
1030  * These are (device specific) constants so we can read them just once.
1031  *
1032  * @return Zero when successful
1033  */
1034 static int BMP085_read_coeffs(void) {
1035   __s32 res;
1036   __u8 coeffs[BMP085_NUM_COEFFS];
1037   char errbuf[1024];
1038
1039   res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_COEFFS,
1040                                       BMP085_NUM_COEFFS, coeffs);
1041   if (res < 0) {
1042     ERROR("barometer: BMP085_read_coeffs - problem reading data: %s",
1043           sstrerror(errno, errbuf, sizeof(errbuf)));
1044     return -1;
1045   }
1046
1047   bmp085_AC1 = ((int16_t)coeffs[0] << 8) | (int16_t)coeffs[1];
1048   bmp085_AC2 = ((int16_t)coeffs[2] << 8) | (int16_t)coeffs[3];
1049   bmp085_AC3 = ((int16_t)coeffs[4] << 8) | (int16_t)coeffs[5];
1050   bmp085_AC4 = ((uint16_t)coeffs[6] << 8) | (uint16_t)coeffs[7];
1051   bmp085_AC5 = ((uint16_t)coeffs[8] << 8) | (uint16_t)coeffs[9];
1052   bmp085_AC6 = ((uint16_t)coeffs[10] << 8) | (uint16_t)coeffs[11];
1053   bmp085_B1 = ((int16_t)coeffs[12] << 8) | (int16_t)coeffs[13];
1054   bmp085_B2 = ((int16_t)coeffs[14] << 8) | (int16_t)coeffs[15];
1055   bmp085_MB = ((int16_t)coeffs[16] << 8) | (int16_t)coeffs[17];
1056   bmp085_MC = ((int16_t)coeffs[18] << 8) | (int16_t)coeffs[19];
1057   bmp085_MD = ((int16_t)coeffs[20] << 8) | (int16_t)coeffs[21];
1058
1059   DEBUG("barometer: BMP085_read_coeffs - AC1=%d, AC2=%d, AC3=%d, AC4=%u,"
1060         " AC5=%u, AC6=%u, B1=%d, B2=%d, MB=%d, MC=%d, MD=%d",
1061         bmp085_AC1, bmp085_AC2, bmp085_AC3, bmp085_AC4, bmp085_AC5, bmp085_AC6,
1062         bmp085_B1, bmp085_B2, bmp085_MB, bmp085_MC, bmp085_MD);
1063
1064   return 0;
1065 }
1066
1067 /**
1068  * Convert raw BMP085 adc values to real data using the sensor coefficients.
1069  *
1070  * @param adc_pressure adc pressure value to be converted
1071  * @param adc_temp     adc temperature value to be converted
1072  * @param pressure     computed real pressure
1073  * @param temperature  computed real temperature
1074  */
1075 static void BMP085_convert_adc_to_real(long adc_pressure, long adc_temperature,
1076                                        double *pressure, double *temperature)
1077
1078 {
1079   long X1, X2, X3;
1080   long B3, B5, B6;
1081   unsigned long B4, B7;
1082
1083   long T;
1084   long P;
1085
1086   /* calculate real temperature */
1087   X1 = ((adc_temperature - bmp085_AC6) * bmp085_AC5) >> 15;
1088   X2 = (bmp085_MC << 11) / (X1 + bmp085_MD);
1089
1090   /* B5, T */
1091   B5 = X1 + X2;
1092   T = (B5 + 8) >> 4;
1093   *temperature = (double)T * 0.1;
1094
1095   /* calculate real pressure */
1096   /* in general X1, X2, X3 are recycled while values of B3, B4, B5, B6 are kept
1097    */
1098
1099   /* B6, B3 */
1100   B6 = B5 - 4000;
1101   X1 = ((bmp085_B2 * ((B6 * B6) >> 12)) >> 11);
1102   X2 = (((long)bmp085_AC2 * B6) >> 11);
1103   X3 = X1 + X2;
1104   B3 = (((((long)bmp085_AC1 * 4) + X3) << bmp085_oversampling) + 2) >> 2;
1105
1106   /* B4 */
1107   X1 = (((long)bmp085_AC3 * B6) >> 13);
1108   X2 = (bmp085_B1 * ((B6 * B6) >> 12)) >> 16;
1109   X3 = ((X1 + X2) + 2) >> 2;
1110   B4 = ((long)bmp085_AC4 * (unsigned long)(X3 + 32768)) >> 15;
1111
1112   /* B7, P */
1113   B7 = (unsigned long)(adc_pressure - B3) * (50000 >> bmp085_oversampling);
1114   if (B7 < 0x80000000) {
1115     P = (B7 << 1) / B4;
1116   } else {
1117     P = (B7 / B4) << 1;
1118   }
1119   X1 = (P >> 8) * (P >> 8);
1120   X1 = (X1 * 3038) >> 16;
1121   X2 = ((-7357) * P) >> 16;
1122   P = P + ((X1 + X2 + 3791) >> 4);
1123
1124   *pressure = P / 100.0; // in [hPa]
1125   DEBUG("barometer: BMP085_convert_adc_to_real - got %lf hPa, %lf C", *pressure,
1126         *temperature);
1127 }
1128
1129 /**
1130  * Read compensated sensor measurements
1131  *
1132  * @param pressure    averaged measured pressure
1133  * @param temperature averaged measured temperature
1134  *
1135  * @return Zero when successful
1136  */
1137 static int BMP085_read(double *pressure, double *temperature) {
1138   __s32 res;
1139   __u8 measBuff[3];
1140
1141   long adc_pressure;
1142   long adc_temperature;
1143
1144   char errbuf[1024];
1145
1146   /* start conversion of temperature */
1147   res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG,
1148                                   BMP085_CMD_CONVERT_TEMP);
1149   if (res < 0) {
1150     ERROR("barometer: BMP085_read - problem requesting temperature conversion: "
1151           "%s",
1152           sstrerror(errno, errbuf, sizeof(errbuf)));
1153     return 1;
1154   }
1155
1156   usleep(BMP085_TIME_CNV_TEMP); /* wait for the conversion */
1157
1158   res =
1159       i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 2, measBuff);
1160   if (res < 0) {
1161     ERROR("barometer: BMP085_read - problem reading temperature data: %s",
1162           sstrerror(errno, errbuf, sizeof(errbuf)));
1163     return 1;
1164   }
1165
1166   adc_temperature = ((unsigned short)measBuff[0] << 8) + measBuff[1];
1167
1168   /* get presure */
1169   res = i2c_smbus_write_byte_data(i2c_bus_fd, BMP085_ADDR_CTRL_REG,
1170                                   bmp085_cmdCnvPress);
1171   if (res < 0) {
1172     ERROR("barometer: BMP085_read - problem requesting pressure conversion: %s",
1173           sstrerror(errno, errbuf, sizeof(errbuf)));
1174     return 1;
1175   }
1176
1177   usleep(bmp085_timeCnvPress); /* wait for the conversion */
1178
1179   res =
1180       i2c_smbus_read_i2c_block_data(i2c_bus_fd, BMP085_ADDR_CONV, 3, measBuff);
1181   if (res < 0) {
1182     ERROR("barometer: BMP085_read - problem reading pressure data: %s",
1183           sstrerror(errno, errbuf, sizeof(errbuf)));
1184     return 1;
1185   }
1186
1187   adc_pressure = (long)((((ulong)measBuff[0] << 16) |
1188                          ((ulong)measBuff[1] << 8) | (ulong)measBuff[2]) >>
1189                         (8 - bmp085_oversampling));
1190
1191   DEBUG("barometer: BMP085_read - raw pressure ADC value = %ld, "
1192         "raw temperature ADC value = %ld",
1193         adc_pressure, adc_temperature);
1194
1195   BMP085_convert_adc_to_real(adc_pressure, adc_temperature, pressure,
1196                              temperature);
1197
1198   return 0;
1199 }
1200
1201 /* ------------------------ Sensor detection ------------------------ */
1202 /**
1203  * Detect presence of a supported sensor.
1204  *
1205  * As a sideeffect will leave set I2C slave address.
1206  * The detection is done in the order BMP085, MPL3115, MPL115 and stops after
1207  * first sensor beeing found.
1208  *
1209  * @return detected sensor type
1210  */
1211 static enum Sensor_type detect_sensor_type(void) {
1212   if (BMP085_detect())
1213     return Sensor_BMP085;
1214
1215   else if (MPL3115_detect())
1216     return Sensor_MPL3115;
1217
1218   else if (MPL115_detect())
1219     return Sensor_MPL115;
1220
1221   return Sensor_none;
1222 }
1223
1224 /* ------------------------ Common functionality ------------------------ */
1225
1226 /**
1227  * Convert absolute pressure (in hPa) to mean sea level pressure
1228  *
1229  * Implemented methods are:
1230  * - MSLP_NONE - no converions, returns absolute pressure
1231  *
1232  * - MSLP_INTERNATIONAL - see
1233  * http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
1234  *           Requires #config_altitude
1235  *
1236  * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See
1237  *                http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
1238  *           Requires both #config_altitude and temperature reference(s).
1239  *
1240  * @param abs_pressure absloute pressure to be converted
1241  *
1242  * @return mean sea level pressure if successful, NAN otherwise
1243  */
1244 static double abs_to_mean_sea_level_pressure(double abs_pressure) {
1245   double mean = -1.0;
1246   double temp = 0.0;
1247   int result = 0;
1248
1249   if (config_normalize >= MSLP_DEU_WETT) {
1250     result = get_reference_temperature(&temp);
1251     if (result) {
1252       return NAN;
1253     }
1254   }
1255
1256   switch (config_normalize) {
1257   case MSLP_NONE:
1258     mean = abs_pressure;
1259     break;
1260
1261   case MSLP_INTERNATIONAL:
1262     mean = abs_pressure / pow(1.0 - 0.0065 * config_altitude / 288.15,
1263                               9.80665 * 0.0289644 / (8.31447 * 0.0065));
1264     break;
1265
1266   case MSLP_DEU_WETT: {
1267     double E; /* humidity */
1268     double x;
1269     if (temp < 9.1)
1270       E = 5.6402 * (-0.0916 + exp(0.06 * temp));
1271     else
1272       E = 18.2194 * (1.0463 - exp(-0.0666 * temp));
1273     x = 9.80665 /
1274         (287.05 * (temp + 273.15 + 0.12 * E + 0.0065 * config_altitude / 2)) *
1275         config_altitude;
1276     mean = abs_pressure * exp(x);
1277   } break;
1278
1279   default:
1280     ERROR(
1281         "barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d",
1282         config_normalize);
1283     mean = abs_pressure;
1284     break;
1285   }
1286
1287   DEBUG("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf hPa, "
1288         "method = %d, meanPressure = %lf hPa",
1289         abs_pressure, config_normalize, mean);
1290
1291   return mean;
1292 }
1293
1294 /* ------------------------ main plugin callbacks ------------------------ */
1295
1296 /**
1297  * Main plugin configuration callback (using simple config)
1298  *
1299  * @param key   configuration key we should process
1300  * @param value configuration value we should process
1301  *
1302  * @return Zero when successful.
1303  */
1304 static int collectd_barometer_config(const char *key, const char *value) {
1305   DEBUG("barometer: collectd_barometer_config");
1306
1307   if (strcasecmp(key, "Device") == 0) {
1308     sfree(config_device);
1309     config_device = strdup(value);
1310   } else if (strcasecmp(key, "Oversampling") == 0) {
1311     int oversampling_tmp = atoi(value);
1312     if (oversampling_tmp < 1 || oversampling_tmp > 1024) {
1313       WARNING("barometer: collectd_barometer_config: invalid oversampling: %d."
1314               " Allowed values are 1 to 1024 (for MPL115) or 1 to 128 (for "
1315               "MPL3115) or 1 to 8 (for BMP085).",
1316               oversampling_tmp);
1317       return 1;
1318     }
1319     config_oversample = oversampling_tmp;
1320   } else if (strcasecmp(key, "Altitude") == 0) {
1321     config_altitude = atof(value);
1322   } else if (strcasecmp(key, "Normalization") == 0) {
1323     int normalize_tmp = atoi(value);
1324     if (normalize_tmp < 0 || normalize_tmp > 2) {
1325       WARNING("barometer: collectd_barometer_config: invalid normalization: %d",
1326               normalize_tmp);
1327       return 1;
1328     }
1329     config_normalize = normalize_tmp;
1330   } else if (strcasecmp(key, "TemperatureSensor") == 0) {
1331     if (temp_list_add(temp_list, value)) {
1332       return -1;
1333     }
1334   } else if (strcasecmp(key, "PressureOffset") == 0) {
1335     config_press_offset = atof(value);
1336   } else if (strcasecmp(key, "TemperatureOffset") == 0) {
1337     config_temp_offset = atof(value);
1338   } else {
1339     return -1;
1340   }
1341
1342   return 0;
1343 }
1344
1345 /**
1346  * Shutdown callback.
1347  *
1348  * Close I2C and delete all the buffers.
1349  *
1350  * @return Zero when successful (at the moment the only possible outcome)
1351  */
1352 static int collectd_barometer_shutdown(void) {
1353   DEBUG("barometer: collectd_barometer_shutdown");
1354
1355   if (sensor_type == Sensor_MPL115) {
1356     averaging_delete(&pressure_averaging);
1357     averaging_delete(&temperature_averaging);
1358
1359     temp_list_delete(&temp_list);
1360   }
1361
1362   if (i2c_bus_fd > 0) {
1363     close(i2c_bus_fd);
1364     i2c_bus_fd = -1;
1365     sfree(config_device);
1366   }
1367
1368   return 0;
1369 }
1370
1371 /**
1372  * Plugin read callback for MPL115.
1373  *
1374  *  Dispatching will create values:
1375  *  - <hostname>/barometer-mpl115/pressure-normalized
1376  *  - <hostname>/barometer-mpl115/pressure-absolute
1377  *  - <hostname>/barometer-mpl115/temperature
1378  *
1379  * @return Zero when successful.
1380  */
1381 static int MPL115_collectd_barometer_read(void) {
1382   int result = 0;
1383
1384   double pressure = 0.0;
1385   double temperature = 0.0;
1386   double norm_pressure = 0.0;
1387
1388   value_list_t vl = VALUE_LIST_INIT;
1389   value_t values[1];
1390
1391   DEBUG("barometer: MPL115_collectd_barometer_read");
1392
1393   if (!configured) {
1394     return -1;
1395   }
1396
1397   /* Rather than delaying init, we will intitialize during first read. This
1398      way at least we have a better chance to have the reference temperature
1399      already available. */
1400   if (!avg_initialized) {
1401     for (int i = 0; i < config_oversample - 1; ++i) {
1402       result = MPL115_read_averaged(&pressure, &temperature);
1403       if (result) {
1404         ERROR("barometer: MPL115_collectd_barometer_read - mpl115 read, "
1405               "ignored during init");
1406       }
1407       DEBUG("barometer: MPL115_collectd_barometer_read - init %d / %d", i + 1,
1408             config_oversample - 1);
1409       usleep(20000);
1410     }
1411     avg_initialized = 1;
1412   }
1413
1414   result = MPL115_read_averaged(&pressure, &temperature);
1415   if (result)
1416     return result;
1417
1418   norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1419
1420   sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1421   sstrncpy(vl.plugin_instance, "mpl115", sizeof(vl.plugin_instance));
1422
1423   vl.values_len = 1;
1424   vl.values = values;
1425
1426   /* dispatch normalized air pressure */
1427   sstrncpy(vl.type, "pressure", sizeof(vl.type));
1428   sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1429   values[0].gauge = norm_pressure;
1430   plugin_dispatch_values(&vl);
1431
1432   /* dispatch absolute air pressure */
1433   sstrncpy(vl.type, "pressure", sizeof(vl.type));
1434   sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1435   values[0].gauge = pressure;
1436   plugin_dispatch_values(&vl);
1437
1438   /* dispatch sensor temperature */
1439   sstrncpy(vl.type, "temperature", sizeof(vl.type));
1440   sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1441   values[0].gauge = temperature;
1442   plugin_dispatch_values(&vl);
1443
1444   return 0;
1445 }
1446
1447 /**
1448  * Plugin read callback for MPL3115.
1449  *
1450  *  Dispatching will create values:
1451  *  - <hostname>/barometer-mpl3115/pressure-normalized
1452  *  - <hostname>/barometer-mpl3115/pressure-absolute
1453  *  - <hostname>/barometer-mpl3115/temperature
1454  *
1455  * @return Zero when successful.
1456  */
1457 static int MPL3115_collectd_barometer_read(void) {
1458   int result = 0;
1459
1460   double pressure = 0.0;
1461   double temperature = 0.0;
1462   double norm_pressure = 0.0;
1463
1464   value_list_t vl = VALUE_LIST_INIT;
1465   value_t values[1];
1466
1467   DEBUG("barometer: MPL3115_collectd_barometer_read");
1468
1469   if (!configured) {
1470     return -1;
1471   }
1472
1473   result = MPL3115_read(&pressure, &temperature);
1474   if (result)
1475     return result;
1476
1477   norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1478
1479   sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1480   sstrncpy(vl.plugin_instance, "mpl3115", sizeof(vl.plugin_instance));
1481
1482   vl.values_len = 1;
1483   vl.values = values;
1484
1485   /* dispatch normalized air pressure */
1486   sstrncpy(vl.type, "pressure", sizeof(vl.type));
1487   sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1488   values[0].gauge = norm_pressure;
1489   plugin_dispatch_values(&vl);
1490
1491   /* dispatch absolute air pressure */
1492   sstrncpy(vl.type, "pressure", sizeof(vl.type));
1493   sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1494   values[0].gauge = pressure;
1495   plugin_dispatch_values(&vl);
1496
1497   /* dispatch sensor temperature */
1498   sstrncpy(vl.type, "temperature", sizeof(vl.type));
1499   sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1500   values[0].gauge = temperature;
1501   plugin_dispatch_values(&vl);
1502
1503   return 0;
1504 }
1505
1506 /**
1507  * Plugin read callback for BMP085.
1508  *
1509  *  Dispatching will create values:
1510  *  - <hostname>/barometer-bmp085/pressure-normalized
1511  *  - <hostname>/barometer-bmp085/pressure-absolute
1512  *  - <hostname>/barometer-bmp085/temperature
1513  *
1514  * @return Zero when successful.
1515  */
1516 static int BMP085_collectd_barometer_read(void) {
1517   int result = 0;
1518
1519   double pressure = 0.0;
1520   double temperature = 0.0;
1521   double norm_pressure = 0.0;
1522
1523   value_list_t vl = VALUE_LIST_INIT;
1524   value_t values[1];
1525
1526   DEBUG("barometer: BMP085_collectd_barometer_read");
1527
1528   if (!configured) {
1529     return -1;
1530   }
1531
1532   result = BMP085_read(&pressure, &temperature);
1533   if (result)
1534     return result;
1535
1536   norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1537
1538   sstrncpy(vl.plugin, "barometer", sizeof(vl.plugin));
1539   sstrncpy(vl.plugin_instance, "bmp085", sizeof(vl.plugin_instance));
1540
1541   vl.values_len = 1;
1542   vl.values = values;
1543
1544   /* dispatch normalized air pressure */
1545   sstrncpy(vl.type, "pressure", sizeof(vl.type));
1546   sstrncpy(vl.type_instance, "normalized", sizeof(vl.type_instance));
1547   values[0].gauge = norm_pressure;
1548   plugin_dispatch_values(&vl);
1549
1550   /* dispatch absolute air pressure */
1551   sstrncpy(vl.type, "pressure", sizeof(vl.type));
1552   sstrncpy(vl.type_instance, "absolute", sizeof(vl.type_instance));
1553   values[0].gauge = pressure;
1554   plugin_dispatch_values(&vl);
1555
1556   /* dispatch sensor temperature */
1557   sstrncpy(vl.type, "temperature", sizeof(vl.type));
1558   sstrncpy(vl.type_instance, "", sizeof(vl.type_instance));
1559   values[0].gauge = temperature;
1560   plugin_dispatch_values(&vl);
1561
1562   return 0;
1563 }
1564
1565 /**
1566  * Initialization callback
1567  *
1568  * Check config, initialize I2C bus access, conversion coefficients and
1569  * averaging
1570  * ring buffers
1571  *
1572  * @return Zero when successful.
1573  */
1574 static int collectd_barometer_init(void) {
1575   char errbuf[1024];
1576
1577   DEBUG("barometer: collectd_barometer_init");
1578
1579   if (config_device == NULL) {
1580     ERROR("barometer: collectd_barometer_init I2C bus device not configured");
1581     return -1;
1582   }
1583
1584   if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude)) {
1585     ERROR("barometer: collectd_barometer_init no altitude configured "
1586           "for mean sea level pressure normalization.");
1587     return -1;
1588   }
1589
1590   if (config_normalize == MSLP_DEU_WETT && temp_list == NULL) {
1591     ERROR("barometer: collectd_barometer_init no temperature reference "
1592           "configured for mean sea level pressure normalization.");
1593     return -1;
1594   }
1595
1596   i2c_bus_fd = open(config_device, O_RDWR);
1597   if (i2c_bus_fd < 0) {
1598     ERROR("barometer: collectd_barometer_init problem opening I2C bus device "
1599           "\"%s\": %s (is loaded mod i2c-dev?)",
1600           config_device, sstrerror(errno, errbuf, sizeof(errbuf)));
1601     return -1;
1602   }
1603
1604   /* detect sensor type - this will also set slave address */
1605   sensor_type = detect_sensor_type();
1606
1607   /* init correct sensor type */
1608   switch (sensor_type) {
1609   /* MPL3115 */
1610   case Sensor_MPL3115: {
1611     MPL3115_adjust_oversampling();
1612
1613     if (MPL3115_init_sensor())
1614       return -1;
1615
1616     plugin_register_read("barometer", MPL3115_collectd_barometer_read);
1617   } break;
1618
1619   /* MPL115 */
1620   case Sensor_MPL115: {
1621     if (averaging_create(&pressure_averaging, config_oversample)) {
1622       ERROR(
1623           "barometer: collectd_barometer_init pressure averaging init failed");
1624       return -1;
1625     }
1626
1627     if (averaging_create(&temperature_averaging, config_oversample)) {
1628       ERROR("barometer: collectd_barometer_init temperature averaging init "
1629             "failed");
1630       return -1;
1631     }
1632
1633     if (MPL115_read_coeffs() < 0)
1634       return -1;
1635
1636     plugin_register_read("barometer", MPL115_collectd_barometer_read);
1637   } break;
1638
1639   /* BMP085 */
1640   case Sensor_BMP085: {
1641     BMP085_adjust_oversampling();
1642
1643     if (BMP085_read_coeffs() < 0)
1644       return -1;
1645
1646     plugin_register_read("barometer", BMP085_collectd_barometer_read);
1647   } break;
1648
1649   /* anything else -> error */
1650   default:
1651     ERROR("barometer: collectd_barometer_init - no supported sensor found");
1652     return -1;
1653   }
1654
1655   configured = 1;
1656   return 0;
1657 }
1658
1659 /* ------------------------ plugin register / entry point
1660  * ------------------------ */
1661
1662 /**
1663  * Plugin "entry" - register all callback.
1664  *
1665  */
1666 void module_register(void) {
1667   plugin_register_config("barometer", collectd_barometer_config, config_keys,
1668                          config_keys_num);
1669   plugin_register_init("barometer", collectd_barometer_init);
1670   plugin_register_shutdown("barometer", collectd_barometer_shutdown);
1671 }