Merge pull request #3339 from jkohen/patch-1
[collectd.git] / src / barometer.c
1 /**
2  * collectd - src/barometer.c
3  *
4  * This program is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published by
6  * the Free Software Foundation; only version 2.1 of the License is
7  * applicable.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
17  *
18  * Authors:
19  *   Tomas Menzl
20  **/
21
22 #include "collectd.h"
23 #include "common.h"
24 #include "utils_cache.h"
25 #include "plugin.h"
26
27 #include <stdint.h>
28 #include <fcntl.h>
29 #include <unistd.h>
30 #include <linux/i2c-dev.h>
31 #include <math.h>
32
33 /* ------------ MPL115 defines ------------ */
34 /* I2C address of the MPL115 sensor */
35 #define MPL115_I2C_ADDRESS          0x60
36                                     
37 /* register addresses */            
38 #define MPL115_ADDR_CONV            0x00
39 #define MPL115_ADDR_COEFFS          0x04
40                                     
41 /* register sizes */                
42 #define MPL115_NUM_CONV             4
43 #define MPL115_NUM_COEFFS           12
44                                     
45 /* commands / addresses */          
46 #define MPL115_CMD_CONVERT_PRESS    0x10
47 #define MPL115_CMD_CONVERT_TEMP     0x11
48 #define MPL115_CMD_CONVERT_BOTH     0x12
49                                     
50 #define MPL115_CONVERSION_RETRIES   5
51
52
53 /* ------------ MPL3115 defines ------------ */
54 /* MPL3115 I2C address */
55 #define MPL3115_I2C_ADDRESS         0x60
56
57 /* register addresses (only the interesting ones) */
58 #define MPL3115_REG_STATUS          0x00
59 #define MPL3115_REG_OUT_P_MSB       0x01
60 #define MPL3115_REG_OUT_P_CSB       0x02
61 #define MPL3115_REG_OUT_P_LSB       0x03
62 #define MPL3115_REG_OUT_T_MSB       0x04
63 #define MPL3115_REG_OUT_T_LSB       0x05
64 #define MPL3115_REG_DR_STATUS       0x06
65 #define MPL3115_REG_WHO_AM_I        0x0C
66 #define MPL3115_REG_SYSMOD          0x11
67 #define MPL3115_REG_PT_DATA_CFG     0x13
68 #define MPL3115_REG_BAR_IN_MSB      0x14
69 #define MPL3115_REG_BAR_IN_LSB      0x15
70 #define MPL3115_REG_CTRL_REG1       0x26
71 #define MPL3115_REG_CTRL_REG2       0x27
72 #define MPL3115_REG_CTRL_REG3       0x28
73 #define MPL3115_REG_CTRL_REG4       0x29
74 #define MPL3115_REG_CTRL_REG5       0x2A
75 #define MPL3115_REG_OFF_P           0x2B
76 #define MPL3115_REG_OFF_T           0x2C
77 #define MPL3115_REG_OFF_H           0x2D
78
79 /* Register values, masks */
80 #define MPL3115_WHO_AM_I_RESP       0xC4
81
82 #define MPL3115_PT_DATA_DREM        0x04
83 #define MPL3115_PT_DATA_PDEF        0x02
84 #define MPL3115_PT_DATA_TDEF        0x01
85                                     
86 #define MPL3115_DR_STATUS_TDR       0x02
87 #define MPL3115_DR_STATUS_PDR       0x04
88 #define MPL3115_DR_STATUS_PTDR      0x08
89 #define MPL3115_DR_STATUS_DR        (MPL3115_DR_STATUS_TDR | MPL3115_DR_STATUS_PDR | MPL3115_DR_STATUS_PTDR)
90                                     
91 #define MPL3115_DR_STATUS_TOW       0x20
92 #define MPL3115_DR_STATUS_POW       0x40
93 #define MPL3115_DR_STATUS_PTOW      0x80
94
95 #define MPL3115_CTRL_REG1_ALT       0x80
96 #define MPL3115_CTRL_REG1_RAW       0x40
97 #define MPL3115_CTRL_REG1_OST_MASK  0x38
98 #define MPL3115_CTRL_REG1_OST_1     0x00
99 #define MPL3115_CTRL_REG1_OST_2     0x08
100 #define MPL3115_CTRL_REG1_OST_4     0x10
101 #define MPL3115_CTRL_REG1_OST_8     0x18
102 #define MPL3115_CTRL_REG1_OST_16    0x20
103 #define MPL3115_CTRL_REG1_OST_32    0x28
104 #define MPL3115_CTRL_REG1_OST_64    0x30
105 #define MPL3115_CTRL_REG1_OST_128   0x38
106 #define MPL3115_CTRL_REG1_RST       0x04
107 #define MPL3115_CTRL_REG1_OST       0x02
108 #define MPL3115_CTRL_REG1_SBYB      0x01
109 #define MPL3115_CTRL_REG1_SBYB_MASK 0xFE
110
111 #define MPL3115_NUM_CONV_VALS       5
112
113
114 /* ------------ Normalization ------------ */
115 /* Mean sea level pressure normalization methods */
116 #define MSLP_NONE          0
117 #define MSLP_INTERNATIONAL 1
118 #define MSLP_DEU_WETT      2
119
120 /** Temperature reference history depth for averaging. See #get_reference_temperature */
121 #define REF_TEMP_AVG_NUM   5
122
123 /* ------------------------------------------ */
124 static const char *config_keys[] =
125 {
126     "Device",
127     "Oversampling",
128     "PressureOffset",    /**< only for MPL3115 */
129     "TemperatureOffset", /**< only for MPL3115 */
130     "Altitude",
131     "Normalization",
132     "TemperatureSensor"
133 };
134
135 static int    config_keys_num     = STATIC_ARRAY_SIZE(config_keys);
136                                   
137 static char * config_device       = NULL;  /**< I2C bus device */
138 static int    config_oversample   = 1;     /**< averaging window */
139
140 static double config_press_offset = 0.0;   /**< pressure offset */
141 static double config_temp_offset  = 0.0;   /**< temperature offset */
142
143 static double config_altitude     = NAN;   /**< altitude */
144 static int    config_normalize    = 0;     /**< normalization method */
145                                   
146 static _Bool  configured          = 0;     /**< the whole plugin config status */
147                                   
148 static int    i2c_bus_fd          = -1;    /**< I2C bus device FD */
149                                   
150 static _Bool  is_MPL3115          = 0;    /**< is this MPL3115? */
151 static __s32  oversample_MPL3115  = 0;    /**< MPL3115 CTRL1 oversample setting */
152
153
154 /* MPL115 conversion coefficients */
155 static double mpl115_coeffA0;
156 static double mpl115_coeffB1;
157 static double mpl115_coeffB2;
158 static double mpl115_coeffC12;
159 static double mpl115_coeffC11;
160 static double mpl115_coeffC22;
161
162 /* ------------------------ averaging ring buffer ------------------------ */
163 /*  Used only for MPL115. MPL3115 supports real oversampling in the device so */
164 /*  no need for any postprocessing. */
165
166 static _Bool avg_initialized = 0;    /**< already initialized by real values */
167
168 typedef struct averaging_s {
169     long int * ring_buffer;
170     int        ring_buffer_size;
171     long int   ring_buffer_sum;
172     int        ring_buffer_head;
173 } averaging_t;
174
175
176 static averaging_t pressure_averaging    = { NULL, 0, 0L, 0 };
177 static averaging_t temperature_averaging = { NULL, 0, 0L, 0 };
178
179
180 /** 
181  * Create / allocate averaging buffer
182  *
183  * The buffer is initialized with zeros.
184  *
185  * @param avg  pointer to ring buffer to be allocated
186  * @param size requested buffer size
187  *
188  * @return Zero when successful
189  */
190 static int averaging_create(averaging_t * avg, int size)
191 {
192     int a;
193
194     avg->ring_buffer = (long int *) malloc(size * sizeof(*avg));
195     if (avg->ring_buffer == NULL)
196     {
197         ERROR ("barometer: averaging_create - ring buffer allocation of size %d failed",
198                size);
199         return -1;
200     }
201
202     for (a=0; a<size; ++a)
203     {
204       avg->ring_buffer[a] = 0L;
205     }
206
207     avg->ring_buffer_size = size;
208     avg->ring_buffer_sum  = 0L;
209     avg->ring_buffer_head = 0;
210
211     return 0;
212 }
213
214
215 /**
216  * Delete / free existing averaging buffer
217  *
218  * @param avg  pointer to the ring buffer to be deleted
219  */
220 static void averaging_delete(averaging_t * avg)
221 {
222     if (avg->ring_buffer != NULL)
223     {
224         free(avg->ring_buffer);
225         avg->ring_buffer = NULL;
226     }
227     avg->ring_buffer_size = 0;
228     avg->ring_buffer_sum  = 0L;
229     avg->ring_buffer_head = 0;
230 }
231
232
233 /*
234  * Add new sample to the averaging buffer
235  *
236  * A new averaged value is returned. Note that till the buffer is full
237  * returned value is inaccurate as it is an average of real values and initial
238  * zeros.
239  *
240  * @param avg    pointer to the ring buffer
241  * @param sample new sample value
242  *
243  * @return Averaged sample value
244  */
245 static double averaging_add_sample(averaging_t * avg, long int sample)
246 {
247     double result;
248
249     avg->ring_buffer_sum += sample - avg->ring_buffer[avg->ring_buffer_head];
250     avg->ring_buffer[avg->ring_buffer_head] = sample;
251     avg->ring_buffer_head = (avg->ring_buffer_head+1) % avg->ring_buffer_size;
252     result = (double)(avg->ring_buffer_sum) / (double)(avg->ring_buffer_size);
253     
254     DEBUG ("barometer: averaging_add_sample - added %ld, result = %lf", 
255            sample, 
256            result);
257
258     return result;
259 }
260
261
262 /* ------------------------ temperature refference ------------------------ */
263
264 /**
265  * Linked list type of temperature sensor references
266  */
267 typedef struct temperature_list_s {
268     char                      * sensor_name; /**< sensor name/reference */
269     size_t                      num_values;  /**< number of values (usually one) */
270     _Bool                       initialized; /**< sensor already provides data */
271     struct temperature_list_s * next;        /**< next in the list */
272 } temperature_list_t;
273
274 static temperature_list_t * temp_list = NULL;
275
276
277 /*
278  * Add new sensor to the temperature reference list
279  *
280  * @param list   the list
281  * @param sensor reference name (as provided by the config file)
282  *
283  * @return Zero when successful
284  */
285 static int temp_list_add(temperature_list_t * list, const char * sensor)
286 {
287     temperature_list_t * new_temp;
288
289     new_temp = (temperature_list_t *) malloc(sizeof(*new_temp));
290     if(new_temp == NULL)
291         return -1;
292
293     new_temp->sensor_name = strdup(sensor);
294     new_temp->initialized = 0;
295     new_temp->num_values = 0;
296     if(new_temp->sensor_name == NULL)
297     {
298         free(new_temp);
299         return -1;
300     }
301
302     new_temp->next = temp_list;
303     temp_list = new_temp;
304     return 0;
305 }
306
307
308 /*
309  * Delete the whole temperature reference list
310  *
311  * @param list the list to be deleted
312  */
313 static void temp_list_delete(temperature_list_t ** list)
314 {
315     temperature_list_t * tmp;
316
317     while (*list != NULL)
318     {
319         tmp = (*list);
320         (*list) = (*list)->next;
321         free(tmp->sensor_name);
322         free(tmp);
323         tmp = NULL;
324     }
325 }
326
327
328 /*
329  * Get reference temperature value
330  *
331  * First initially uc_get_rate_by_name is tried. At the startup due to nondeterministic
332  * order the temperature may not be read yet (then it fails and first measurment gives
333  * only absolute air pressure reading which is acceptable). Once it succedes (should be
334  * second measurement at the latest) we use average of few last readings from
335  * uc_get_history_by_name. It may take few readings to start filling so again we use
336  * uc_get_rate_by_name as a fallback.
337  * The idea is to use basic "noise" filtering (history averaging) across all the values
338  * which given sensor provides (up to given depth). Then we get minimum among
339  * the sensors.
340  *
341  * @param result where the result is stored. When not available NAN is stored.
342  *
343  * @return Zero when successful
344  */
345 static int get_reference_temperature(double * result)
346 {
347     temperature_list_t * list = temp_list;
348
349     gauge_t * values = NULL;   /**< rate values */
350     size_t    values_num = 0;  /**< number of rate values */
351     int i;
352
353     gauge_t values_history[REF_TEMP_AVG_NUM];
354
355     double avg_sum;  /**< Value sum for computing average */
356     int    avg_num;  /**< Number of values for computing average */
357     double average;  /**< Resulting value average */
358
359     *result = NAN;
360
361     while(list != NULL)
362     {
363         avg_sum = 0.0;
364         avg_num = 0;
365
366         /* First time need to read current rate to learn how many values are
367            there (typically for temperature it would be just one).
368            We do not expect dynamic changing of number of temperarure values
369            in runtime yet (are there any such cases?). */
370         if(!list->initialized)
371         {
372             if(uc_get_rate_by_name(list->sensor_name,
373                                    &values,
374                                    &values_num))
375             {
376                 DEBUG ("barometer: get_reference_temperature - rate \"%s\" not found yet",
377                        list->sensor_name);
378                 list = list->next;
379                 continue;
380             }
381
382             DEBUG ("barometer: get_reference_temperature - initialize \"%s\", %zu vals",
383                    list->sensor_name,
384                    values_num);
385
386             list->initialized = 1;
387             list->num_values = values_num;
388
389             for(i=0; i<values_num; ++i)
390             {
391                 DEBUG ("barometer: get_reference_temperature - rate %d: %lf **",
392                        i,
393                        values[i]);
394                 if(!isnan(values[i]))
395                 {
396                     avg_sum += values[i];
397                     ++avg_num;
398                 }
399             }
400             free(values);
401             values = NULL;
402         }
403
404         /* It is OK to get here the first time as well, in the worst case
405            the history will full of NANs. */
406         if(uc_get_history_by_name(list->sensor_name,
407                                   values_history,
408                                   REF_TEMP_AVG_NUM,
409                                   list->num_values))
410         {
411             ERROR ("barometer: get_reference_temperature - history \"%s\" lost",
412                    list->sensor_name);
413             list->initialized = 0;
414             list->num_values = 0;
415             list = list->next;
416             continue;
417         }
418             
419         for(i=0; i<REF_TEMP_AVG_NUM*list->num_values; ++i)
420         {
421             DEBUG ("barometer: get_reference_temperature - history %d: %lf",
422                    i,
423                    values_history[i]);
424             if(!isnan(values_history[i]))
425             {
426                 avg_sum += values_history[i];
427                 ++avg_num;
428             }
429         }
430
431         if(avg_num == 0)   /* still no history? fallback to current */
432         {
433             if(uc_get_rate_by_name(list->sensor_name,
434                                    &values,
435                                    &values_num))
436             {
437                 ERROR ("barometer: get_reference_temperature - rate \"%s\" lost",
438                        list->sensor_name);
439                 list->initialized = 0;
440                 list->num_values = 0;
441                 list = list->next;
442                 continue;
443             }
444
445             for(i=0; i<values_num; ++i)
446             {
447                 DEBUG ("barometer: get_reference_temperature - rate last %d: %lf **",
448                        i,
449                        values[i]);
450                 if(!isnan(values[i]))
451                 {
452                     avg_sum += values[i];
453                     ++avg_num;
454                 }
455             }
456             free(values);
457             values = NULL;
458         }
459
460         if(avg_num == 0)
461         {
462             ERROR ("barometer: get_reference_temperature - could not read \"%s\"",
463                    list->sensor_name);
464             list->initialized = 0;
465             list->num_values = 0;
466         }
467         else
468         {
469             average = avg_sum / (double) avg_num;
470             if(isnan(*result))
471                 *result=average;
472             else if(*result>average)
473                 *result=average;
474         }
475         list = list->next;
476     }  /* while sensor list */
477     
478     if(*result == NAN)
479     {
480         ERROR("barometer: get_reference_temperature - no sensor available (yet?)");
481         return -1;
482     }
483     DEBUG ("barometer: get_reference_temperature - temp is %lf", *result);
484     return 0;
485 }
486
487 /* ------------------------ MPL115 access ------------------------ */
488
489 /** 
490  * Read the MPL115 sensor conversion coefficients.
491  *
492  * These are (device specific) constants so we can read them just once.
493  *
494  * @return Zero when successful
495  */
496 static int MPL115_read_coeffs(void)
497 {
498     uint8_t mpl115_coeffs[MPL115_NUM_COEFFS]; 
499     int32_t res;
500
501     int8_t  sia0MSB, sia0LSB, sib1MSB, sib1LSB, sib2MSB, sib2LSB;
502     int8_t  sic12MSB, sic12LSB, sic11MSB, sic11LSB, sic22MSB, sic22LSB;
503     int16_t sia0, sib1, sib2, sic12, sic11, sic22;
504       
505     char errbuf[1024];
506
507     res = i2c_smbus_read_i2c_block_data(i2c_bus_fd, 
508                                         MPL115_ADDR_COEFFS, 
509                                         MPL115_NUM_COEFFS, 
510                                         mpl115_coeffs);
511     if (res < 0)
512     {
513         ERROR ("barometer: read_mpl115_coeffs - problem reading data: %s",
514                sstrerror (errno, errbuf, sizeof (errbuf)));
515         return -1;
516     }
517    
518     /* Using perhaps less elegant/efficient code, but more readable. */
519     /* a0: 16total 1sign 12int 4fract 0pad */
520     sia0MSB = mpl115_coeffs[0];
521     sia0LSB = mpl115_coeffs[1];
522     sia0 = (int16_t) sia0MSB <<8;          /* s16 type, Shift to MSB */
523     sia0 += (int16_t) sia0LSB & 0x00FF;    /* Add LSB to 16bit number */
524     mpl115_coeffA0 = (double) (sia0);
525     mpl115_coeffA0 /= 8.0;                 /* 3 fract bits */
526     
527     /* b1: 16total 1sign 2int 13fract 0pad */
528     sib1MSB= mpl115_coeffs[2];
529     sib1LSB= mpl115_coeffs[3];
530     sib1 = sib1MSB <<8;                    /* Shift to MSB */
531     sib1 += sib1LSB & 0x00FF;              /* Add LSB to 16bit number */
532     mpl115_coeffB1 = (double) (sib1);
533     mpl115_coeffB1 /= 8192.0;              /* 13 fract */
534     
535     /* b2: 16total 1sign 1int 14fract 0pad */
536     sib2MSB= mpl115_coeffs[4];
537     sib2LSB= mpl115_coeffs[5];
538     sib2 = sib2MSB <<8;                     /* Shift to MSB */
539     sib2 += sib2LSB & 0x00FF;               /* Add LSB to 16bit number */
540     mpl115_coeffB2 = (double) (sib2);
541     mpl115_coeffB2 /= 16384.0;              /* 14 fract */
542
543     /* c12: 14total 1sign 0int 13fract 9pad */
544     sic12MSB= mpl115_coeffs[6];
545     sic12LSB= mpl115_coeffs[7];
546     sic12 = sic12MSB <<8;                   /* Shift to MSB only by 8 for MSB */
547     sic12 += sic12LSB & 0x00FF;
548     mpl115_coeffC12 = (double) (sic12);
549     mpl115_coeffC12 /= 4.0;                 /* 16-14=2 */
550     mpl115_coeffC12 /= 4194304.0;           /* 13+9=22 fract */
551
552     /* c11: 11total 1sign 0int 11fract 11pad */
553     sic11MSB= mpl115_coeffs[8];
554     sic11LSB= mpl115_coeffs[9];
555     sic11 = sic11MSB <<8;                   /* Shift to MSB only by 8 for MSB */
556     sic11 += sic11LSB & 0x00FF;
557     mpl115_coeffC11 = (double) (sic11);
558     mpl115_coeffC11 /= 32.0;               /* 16-11=5 */
559     mpl115_coeffC11 /= 4194304.0;          /* 11+11=22 fract */
560
561     /* c12: 11total 1sign 0int 10fract 15pad */
562     sic22MSB= mpl115_coeffs[10];
563     sic22LSB= mpl115_coeffs[11];
564     sic22 = sic22MSB <<8;                   /* Shift to MSB only by 8 for MSB */
565     sic22 += sic22LSB & 0x00FF;
566     mpl115_coeffC22 = (double) (sic22);
567     mpl115_coeffC22 /= 32.0; //16-11=5
568     mpl115_coeffC22 /= 33554432.0;          /* 10+15=25 fract */
569
570     DEBUG("barometer: read_mpl115_coeffs: a0=%lf, b1=%lf, b2=%lf, c12=%lf, c11=%lf, c22=%lf",
571           mpl115_coeffA0, 
572           mpl115_coeffB1, 
573           mpl115_coeffB2, 
574           mpl115_coeffC12, 
575           mpl115_coeffC11, 
576           mpl115_coeffC22);
577     return 0;
578 }
579
580
581 /*
582  * Convert raw adc values to real data using the sensor coefficients.
583  *
584  * @param adc_pressure adc pressure value to be converted
585  * @param adc_temp     adc temperature value to be converted
586  * @param pressure     computed real pressure
587  * @param temperature  computed real temperature
588  */
589 static void MPL115_convert_adc_to_real(double   adc_pressure,
590                                        double   adc_temp,
591                                        double * pressure,
592                                        double * temperature)
593 {
594     double Pcomp;
595     Pcomp = mpl115_coeffA0 +                                            \
596         (mpl115_coeffB1 + mpl115_coeffC11*adc_pressure + mpl115_coeffC12*adc_temp) * adc_pressure + \
597         (mpl115_coeffB2 + mpl115_coeffC22*adc_temp) * adc_temp;
598     
599     *pressure = ((1150.0-500.0) * Pcomp / 1023.0) + 500.0;
600     *temperature = (472.0 - adc_temp) / 5.35 + 25.0;
601     DEBUG ("barometer: convert_adc_to_real - got %lf hPa, %lf C",
602            *pressure,
603            *temperature);
604 }
605
606
607 /** 
608  * Read sensor averegaed measurements
609  *
610  * @param pressure    averaged measured pressure
611  * @param temperature averaged measured temperature
612  *
613  * @return Zero when successful
614  */
615 static int MPL115_read_averaged(double * pressure, double * temperature)
616 {
617     uint8_t mpl115_conv[MPL115_NUM_CONV]; 
618     int8_t  res;
619     int     retries;
620     int     conv_pressure;
621     int     conv_temperature;
622     double  adc_pressure;
623     double  adc_temperature;
624     char    errbuf[1024];
625
626     *pressure    = 0.0;
627     *temperature = 0.0;
628    
629     /* start conversion of both temp and presure */
630     retries = MPL115_CONVERSION_RETRIES;
631     while (retries>0)
632     {
633         /* write 1 to start conversion */
634         res = i2c_smbus_write_byte_data (i2c_bus_fd,
635                                          MPL115_CMD_CONVERT_BOTH,
636                                          0x01);
637         if (res >= 0)
638             break;
639
640         --retries;
641         if(retries>0)
642         {
643             ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, " \
644                    "will retry at most %d more times",
645                    sstrerror (errno, errbuf, sizeof (errbuf)),
646                    retries);
647         }
648         else
649         {
650             ERROR ("barometer: MPL115_read_averaged - requesting conversion: %s, "\
651                    "too many failed retries",
652                    sstrerror (errno, errbuf, sizeof (errbuf)));
653             return -1;
654         }
655     }
656
657     usleep (10000); /* wait 10ms for the conversion */
658
659     retries=MPL115_CONVERSION_RETRIES;
660     while (retries>0)
661     {
662         res = i2c_smbus_read_i2c_block_data(i2c_bus_fd,
663                                             MPL115_ADDR_CONV,
664                                             MPL115_NUM_CONV,
665                                             mpl115_conv); 
666         if (res >= 0)
667             break;
668
669         --retries;
670         if (retries>0)
671         {
672             ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \
673                    "will retry at most %d more times",
674                    sstrerror (errno, errbuf, sizeof (errbuf)),
675                    retries);
676         }
677         else
678         {
679             ERROR ("barometer: MPL115_read_averaged - reading conversion: %s, " \
680                    "too many failed retries",
681                    sstrerror (errno, errbuf, sizeof (errbuf)));
682             return -1;
683         }
684     }
685     
686     conv_pressure    = ((mpl115_conv[0] << 8) | mpl115_conv[1]) >> 6;
687     conv_temperature = ((mpl115_conv[2] << 8) | mpl115_conv[3]) >> 6;
688     DEBUG ("barometer: MPL115_read_averaged, raw pressure ADC value = %d, " \
689            "raw temperature ADC value = %d",
690            conv_pressure,
691            conv_temperature);
692
693     adc_pressure    = averaging_add_sample (&pressure_averaging, conv_pressure);
694     adc_temperature = averaging_add_sample (&temperature_averaging, conv_temperature);
695
696     MPL115_convert_adc_to_real(adc_pressure, adc_temperature, pressure, temperature);
697
698     DEBUG ("barometer: MPL115_read_averaged - averaged ADC pressure = %lf / temperature = %lf, " \
699            "real pressure = %lf hPa / temperature = %lf C",
700            adc_pressure,
701            adc_temperature,
702            *pressure,
703            *temperature);
704     
705     return 0;
706 }
707
708 /* ------------------------ MPL3115 access ------------------------ */
709
710 /** 
711  * Detect presence of a MPL3115 pressure sensor by checking register "WHO AM I"
712  * 
713  * @return 1 if MPL3115, 0 otherwise
714  */
715 static int MPL3115_detect(void)
716 {
717     __s32 res;
718
719     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_WHO_AM_I);
720     if(res == MPL3115_WHO_AM_I_RESP)
721     {
722         DEBUG ("barometer: MPL3115_detect - positive detection");
723         return 1;
724     }
725
726     DEBUG ("barometer: MPL3115_detect - negative detection");
727     return 0;
728 }
729
730 /** 
731  * Adjusts oversampling to values supported by MPL3115
732  *
733  * MPL3115 supports only power of 2 in the range 1 to 128. 
734  */
735 static void MPL3115_adjust_oversampling(void)
736 {
737     int new_val = 0;
738
739     if(config_oversample > 100)
740     {
741         new_val = 128;
742         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_128;
743     }
744     else if(config_oversample > 48)
745     {
746         new_val = 64;
747         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_64;
748     }
749     else if(config_oversample > 24)
750     {
751         new_val = 32;
752         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_32;
753     }
754     else if(config_oversample > 12)
755     {
756         new_val = 16;
757         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_16;
758     }
759     else if(config_oversample > 6)
760     {
761         new_val = 8;
762         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_8;
763     }
764     else if(config_oversample > 3)
765     {
766         new_val = 4;
767         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_4;
768     }
769     else if(config_oversample > 1)
770     {
771         new_val = 2;
772         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_2;
773     }
774     else
775     {
776         new_val = 1;
777         oversample_MPL3115 = MPL3115_CTRL_REG1_OST_1;
778     }
779
780     DEBUG("barometer: correcting oversampling for MPL3115 from %d to %d",
781           config_oversample, 
782           new_val);
783     config_oversample = new_val;
784 }
785
786 /** 
787  * Read sensor averegaed measurements
788  *
789  * @param pressure    averaged measured pressure
790  * @param temperature averaged measured temperature
791  *
792  * @return Zero when successful
793  */
794 static int MPL3115_read(double * pressure, double * temperature)
795 {
796     __s32 res;
797     __s32 ctrl ;
798     __u8 data[MPL3115_NUM_CONV_VALS];
799     long int tmp_value = 0;
800     char errbuf[1024];
801     
802     /* Set Active - activate the device from standby */
803     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_CTRL_REG1);
804     if (res < 0)
805     {
806         ERROR ("barometer: MPL3115_read - cannot read CTRL_REG1: %s",
807                sstrerror (errno, errbuf, sizeof (errbuf)));
808         return 1;
809     }
810     ctrl = res;
811     res = i2c_smbus_write_byte_data(i2c_bus_fd, 
812                                     MPL3115_REG_CTRL_REG1, 
813                                     ctrl | MPL3115_CTRL_REG1_SBYB);
814     if (res < 0)
815     {
816         ERROR ("barometer: MPL3115_read - problem activating: %s",
817                sstrerror (errno, errbuf, sizeof (errbuf)));
818         return 1;
819     }
820     
821     /* base sleep is 5ms x OST */
822     usleep(5000 * config_oversample);
823       
824     /* check the flags/status if ready */
825     res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
826     if (res < 0)
827     {
828         ERROR ("barometer: MPL3115_read - cannot read status register: %s",
829                sstrerror (errno, errbuf, sizeof (errbuf)));
830         return 1;
831     }
832     
833     while ((res & MPL3115_DR_STATUS_DR) != MPL3115_DR_STATUS_DR)
834     {
835         /* try some extra sleep... */
836         usleep(10000);
837         
838         /* ... and repeat the check. The conversion has to finish sooner or later. */
839         res = i2c_smbus_read_byte_data(i2c_bus_fd, MPL3115_REG_STATUS);
840         if (res < 0)
841         {
842             ERROR ("barometer: MPL3115_read - cannot read status register: %s",
843                    sstrerror (errno, errbuf, sizeof (errbuf)));
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, 
850                                         MPL3115_REG_OUT_P_MSB, 
851                                         MPL3115_NUM_CONV_VALS,
852                                         data);
853     if (res < 0)
854     {
855         ERROR ("barometer: MPL3115_read - cannot read data registers: %s",
856                sstrerror (errno, errbuf, sizeof (errbuf)));
857         return 1;
858     }
859     
860     tmp_value = (data[0] << 16) | (data[1] << 8) | data[2];
861     *pressure = ((double) tmp_value) / 4.0 / 16.0 / 100.0;
862     DEBUG ("barometer: MPL3115_read, absolute pressure = %lf hPa", *pressure);
863     
864     if(data[3] > 0x7F)
865     {
866         data[3] = ~data[3] + 1;
867         *temperature = data[3];
868         *temperature = - *temperature;
869     }
870     else
871     {
872         *temperature = data[3];
873     }
874     
875     *temperature += (double)(data[4]) / 256.0;
876     DEBUG ("barometer: MPL3115_read, temperature = %lf C", *temperature);
877     
878     return 0;
879 }
880
881 /** 
882  * Initialize MPL3115 for barometeric measurements
883  * 
884  * @return 0 if successful
885  */
886 static int MPL3115_init_sensor(void)
887 {
888     __s32 res;
889     __s8 offset;
890     char errbuf[1024];
891     
892     /* Reset the sensor. It will reset immediately without ACKing */
893     /* the transaction, so no error handling here. */
894     i2c_smbus_write_byte_data(i2c_bus_fd, 
895                               MPL3115_REG_CTRL_REG1, 
896                               MPL3115_CTRL_REG1_RST);
897     
898     /* wait some time for the reset to finish */
899     usleep(100000);
900
901     /* now it should be in standby already so we can go and configure it */
902     
903     /*  Set temperature offset. */
904     /*  result = ADCtemp + offset [C] */
905     offset = (__s8) (config_temp_offset * 16.0);
906     res = i2c_smbus_write_byte_data(i2c_bus_fd, MPL3115_REG_OFF_T, offset);
907     if (res < 0)
908     {
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     {
920         ERROR ("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, 
927                                     MPL3115_REG_PT_DATA_CFG,
928                                     MPL3115_PT_DATA_DREM        \
929                                     | MPL3115_PT_DATA_PDEF      \
930                                     | MPL3115_PT_DATA_TDEF);
931     if (res < 0)
932     {
933         ERROR ("barometer: MPL3115_init_sensor - problem setting PT_DATA_CFG: %s",
934                sstrerror (errno, errbuf, sizeof (errbuf)));
935         return -1;
936     }
937
938     /* Set to barometer with an OSR */ 
939     res = i2c_smbus_write_byte_data(i2c_bus_fd, 
940                                     MPL3115_REG_CTRL_REG1, 
941                                     oversample_MPL3115);
942     if (res < 0)
943     {
944         ERROR ("barometer: MPL3115_init_sensor - problem configuring CTRL_REG1: %s",
945                sstrerror (errno, errbuf, sizeof (errbuf)));
946         return -1;
947     }
948
949     return 0;
950 }
951
952
953 /* ------------------------ Common functionality ------------------------ */
954
955 /**
956  * Convert absolute pressure (in hPa) to mean sea level pressure
957  *
958  * Implemented methods are:
959  * - MSLP_NONE - no converions, returns absolute pressure
960  *
961  * - MSLP_INTERNATIONAL - see http://en.wikipedia.org/wiki/Atmospheric_pressure#Altitude_atmospheric_pressure_variation
962  *           Requires #config_altitude
963  *
964  * - MSLP_DEU_WETT - formula as recommended by the Deutsche Wetterdienst. See 
965  *                http://de.wikipedia.org/wiki/Barometrische_H%C3%B6henformel#Theorie
966  *           Requires both #config_altitude and temperature reference(s).
967  *
968  * @param abs_pressure absloute pressure to be converted
969  *
970  * @return mean sea level pressure if successful, NAN otherwise
971  */
972 static double abs_to_mean_sea_level_pressure(double abs_pressure)
973 {
974     double mean = -1.0;
975     double temp = 0.0;
976     int result = 0;
977
978     DEBUG ("barometer: abs_to_mean_sea_level_pressure: absPressure = %lf, method = %d",
979            abs_pressure,
980            config_normalize);
981
982     if (config_normalize >= MSLP_DEU_WETT)
983     {
984         result = get_reference_temperature(&temp);
985         if(result)
986         {
987             return NAN;
988         }
989     }
990
991     switch(config_normalize)
992     {
993     case MSLP_NONE:
994         mean = abs_pressure;
995         break;
996         
997     case MSLP_INTERNATIONAL:
998         mean = abs_pressure / \
999             pow(1.0 - 0.0065*config_altitude/288.15, 0.0065*0.0289644/(8.31447*0.0065));
1000         break;
1001         
1002     case MSLP_DEU_WETT:
1003     {
1004         double E; /* humidity */
1005         double x;
1006         if(temp<9.1)
1007             E = 5.6402 * (-0.0916 + exp(0.06*temp) );
1008         else
1009             E = 18.2194 * (1.0463 - exp(-0.0666*temp) );
1010         x = 9.80665 / (287.05 * (temp+273.15 + 0.12*E + 0.0065*config_altitude/2)) * config_altitude;
1011         mean = abs_pressure * exp(x);
1012     }
1013     break;
1014
1015     default:
1016         ERROR ("barometer: abs_to_mean_sea_level_pressure: wrong conversion method %d", 
1017                config_normalize);
1018         mean = abs_pressure;
1019         break;
1020     }
1021
1022     return mean; 
1023 }
1024
1025 /* ------------------------ main plugin callbacks ------------------------ */
1026
1027 /** 
1028  * Main plugin configuration callback (using simple config)
1029  * 
1030  * @param key   configuration key we should process
1031  * @param value configuration value we should process
1032  * 
1033  * @return Zero when successful.
1034  */
1035 static int collectd_barometer_config (const char *key, const char *value)
1036 {
1037     DEBUG("barometer: collectd_barometer_config");
1038
1039     if (strcasecmp (key, "Device") == 0)
1040     {
1041         sfree (config_device);
1042         config_device = strdup (value);
1043     }
1044     else if (strcasecmp (key, "Oversampling") == 0)
1045     {
1046         int oversampling_tmp = atoi (value);
1047         if (oversampling_tmp < 1 || oversampling_tmp > 1024)
1048         {
1049             WARNING ("barometer: collectd_barometer_config: invalid oversampling: %d." \
1050                      " Allowed values are 1 to 1024 (for MPL115) or 128 (for MPL3115).",
1051                      oversampling_tmp);
1052             return 1;
1053         }
1054         config_oversample = oversampling_tmp;
1055     }
1056     else if (strcasecmp (key, "Altitude") == 0)
1057     {
1058         config_altitude = atof (value);
1059     }
1060     else if (strcasecmp (key, "Normalization") == 0)
1061     {
1062         int normalize_tmp = atoi (value);
1063         if (normalize_tmp < 0 || normalize_tmp > 2)
1064         {
1065             WARNING ("barometer: collectd_barometer_config: invalid normalization: %d",
1066                      normalize_tmp);
1067             return 1;
1068         }
1069         config_normalize = normalize_tmp;
1070     }
1071     else if (strcasecmp (key, "TemperatureSensor") == 0)
1072     {
1073         if(temp_list_add(temp_list, value))
1074         {
1075             return -1;
1076         }
1077     }
1078     else if (strcasecmp (key, "PressureOffset") == 0)
1079     {
1080         config_press_offset = atof(value);
1081     }
1082     else if (strcasecmp (key, "TemperatureOffset") == 0)
1083     {
1084         config_temp_offset = atof(value);
1085     }
1086     else 
1087     {
1088         return -1;
1089     }
1090
1091     return 0;
1092 }
1093
1094
1095 /** 
1096  * Shutdown callback.
1097  * 
1098  * Close I2C and delete all the buffers.
1099  * 
1100  * @return Zero when successful (at the moment the only possible outcome)
1101  */
1102 static int collectd_barometer_shutdown(void)
1103 {
1104     DEBUG ("barometer: collectd_barometer_shutdown");
1105
1106     if(!is_MPL3115)
1107     {
1108         averaging_delete (&pressure_averaging);
1109         averaging_delete (&temperature_averaging);
1110
1111         temp_list_delete(&temp_list);
1112     }
1113
1114     if (i2c_bus_fd > 0)
1115     {
1116         close (i2c_bus_fd);
1117         i2c_bus_fd = -1;
1118         sfree (config_device);
1119     }
1120
1121     return 0;
1122 }
1123
1124
1125 /** 
1126  * Plugin read callback for MPL115.
1127  * 
1128  *  Dispatching will create values:
1129  *  - <hostname>/barometer-mpl115/pressure-normalized
1130  *  - <hostname>/barometer-mpl115/pressure-absolute
1131  *  - <hostname>/barometer-mpl115/temperature
1132  *
1133  * @return Zero when successful.
1134  */
1135 static int MPL115_collectd_barometer_read (void)
1136 {
1137     int result = 0;
1138
1139     double pressure        = 0.0;
1140     double temperature     = 0.0;
1141     double norm_pressure   = 0.0;
1142
1143     value_list_t vl = VALUE_LIST_INIT;
1144     value_t      values[1];
1145     
1146     DEBUG("barometer: MPL115_collectd_barometer_read");
1147
1148     if (!configured)
1149     {
1150         return -1;
1151     }
1152
1153     /* Rather than delaying init, we will intitialize during first read. This
1154        way at least we have a better chance to have the reference temperature
1155        already available. */
1156     if(!avg_initialized)
1157     {
1158         int i;
1159         for(i=0; i<config_oversample-1; ++i)
1160         {
1161             result = MPL115_read_averaged(&pressure, &temperature);
1162             if(result)
1163             {
1164                 ERROR ("barometer: MPL115_collectd_barometer_read - mpl115 read, ignored during init");
1165             }
1166             DEBUG("barometer: MPL115_collectd_barometer_read - init %d / %d", i+1, config_oversample-1);
1167             usleep(20000);
1168         }
1169         avg_initialized = 1;
1170     }
1171
1172     result = MPL115_read_averaged(&pressure, &temperature);
1173     if(result)
1174         return result;
1175
1176     norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1177
1178     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
1179     sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
1180     sstrncpy (vl.plugin_instance, "mpl115", sizeof (vl.plugin_instance));
1181
1182     vl.values_len = 1;
1183     vl.values = values;
1184
1185     /* dispatch normalized air pressure */
1186     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1187     sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
1188     values[0].gauge = norm_pressure;
1189     plugin_dispatch_values (&vl);
1190
1191     /* dispatch absolute air pressure */
1192     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1193     sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
1194     values[0].gauge = pressure;
1195     plugin_dispatch_values (&vl);
1196
1197     /* dispatch sensor temperature */
1198     sstrncpy (vl.type, "temperature", sizeof (vl.type));
1199     sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
1200     values[0].gauge = temperature;
1201     plugin_dispatch_values (&vl);
1202
1203     return 0;
1204 }
1205
1206
1207 /** 
1208  * Plugin read callback for MPL3115.
1209  * 
1210  *  Dispatching will create values:
1211  *  - <hostname>/barometer-mpl3115/pressure-normalized
1212  *  - <hostname>/barometer-mpl3115/pressure-absolute
1213  *  - <hostname>/barometer-mpl3115/temperature
1214  *
1215  * @return Zero when successful.
1216  */
1217 static int MPL3115_collectd_barometer_read (void)
1218 {
1219     int result = 0;
1220     
1221     double pressure        = 0.0;
1222     double temperature     = 0.0;
1223     double norm_pressure   = 0.0;
1224     
1225     value_list_t vl = VALUE_LIST_INIT;
1226     value_t      values[1];
1227     
1228     DEBUG("barometer: MPL3115_collectd_barometer_read");
1229     
1230     if (!configured)
1231     {
1232         return -1;
1233     }
1234     
1235     result = MPL3115_read(&pressure, &temperature);
1236     if(result)
1237         return result;
1238
1239     norm_pressure = abs_to_mean_sea_level_pressure(pressure);
1240
1241     sstrncpy (vl.host, hostname_g, sizeof (vl.host));
1242     sstrncpy (vl.plugin, "barometer", sizeof (vl.plugin));
1243     sstrncpy (vl.plugin_instance, "mpl3115", sizeof (vl.plugin_instance));
1244
1245     vl.values_len = 1;
1246     vl.values = values;
1247
1248     /* dispatch normalized air pressure */
1249     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1250     sstrncpy (vl.type_instance, "normalized", sizeof (vl.type_instance));
1251     values[0].gauge = norm_pressure;
1252     plugin_dispatch_values (&vl);
1253
1254     /* dispatch absolute air pressure */
1255     sstrncpy (vl.type, "pressure", sizeof (vl.type));
1256     sstrncpy (vl.type_instance, "absolute", sizeof (vl.type_instance));
1257     values[0].gauge = pressure;
1258     plugin_dispatch_values (&vl);
1259
1260     /* dispatch sensor temperature */
1261     sstrncpy (vl.type, "temperature", sizeof (vl.type));
1262     sstrncpy (vl.type_instance, "", sizeof (vl.type_instance));
1263     values[0].gauge = temperature;
1264     plugin_dispatch_values (&vl);
1265
1266     return 0;
1267 }
1268
1269
1270 /** 
1271  * Initialization callback
1272  * 
1273  * Check config, initialize I2C bus access, conversion coefficients and averaging
1274  * ring buffers
1275  * 
1276  * @return Zero when successful.
1277  */
1278 static int collectd_barometer_init (void)
1279 {
1280     char errbuf[1024];
1281
1282     DEBUG ("barometer: collectd_barometer_init");
1283
1284     if (config_device == NULL)
1285     {
1286         ERROR("barometer: collectd_barometer_init I2C bus device not configured");
1287         return -1;
1288     }
1289
1290     if (config_normalize >= MSLP_INTERNATIONAL && isnan(config_altitude))
1291     {
1292         ERROR("barometer: collectd_barometer_init no altitude configured " \
1293               "for mean sea level pressure normalization.");
1294         return -1;
1295     }
1296
1297     if (config_normalize == MSLP_DEU_WETT
1298         &&
1299         temp_list == NULL)
1300     {
1301         ERROR("barometer: collectd_barometer_init no temperature reference "\
1302               "configured for mean sea level pressure normalization.");
1303         return -1;
1304     }
1305
1306
1307     i2c_bus_fd = open(config_device, O_RDWR);
1308     if (i2c_bus_fd < 0)
1309     {
1310         ERROR ("barometer: collectd_barometer_init problem opening I2C bus device \"%s\": %s (is loaded mod i2c-dev?)",
1311                config_device,
1312                sstrerror (errno, errbuf, sizeof (errbuf)));
1313         return -1;
1314     }
1315
1316     if (ioctl(i2c_bus_fd, I2C_SLAVE_FORCE, MPL115_I2C_ADDRESS) < 0)
1317     {
1318         ERROR("barometer: collectd_barometer_init problem setting i2c slave address to 0x%02X: %s",
1319               MPL115_I2C_ADDRESS,
1320               sstrerror (errno, errbuf, sizeof (errbuf)));
1321         return -1;
1322     }
1323
1324     /* detect sensor type - MPL115 or MPL3115 */
1325     is_MPL3115 = MPL3115_detect();
1326
1327     /* init correct sensor type */
1328     if(is_MPL3115) /* MPL3115 */
1329     {
1330         MPL3115_adjust_oversampling();
1331
1332         if(MPL3115_init_sensor())
1333             return -1;
1334
1335         plugin_register_read ("barometer", MPL3115_collectd_barometer_read);
1336     }
1337     else /* MPL115 */
1338     {
1339         if (averaging_create (&pressure_averaging, config_oversample))
1340         {
1341             ERROR("barometer: collectd_barometer_init pressure averaging init failed");
1342             return -1;
1343         }
1344         
1345         if (averaging_create (&temperature_averaging, config_oversample))
1346         {
1347             ERROR("barometer: collectd_barometer_init temperature averaging init failed");
1348             return -1;
1349         }
1350         
1351         if (MPL115_read_coeffs() < 0)
1352             return -1;
1353
1354         plugin_register_read ("barometer", MPL115_collectd_barometer_read);
1355     }
1356
1357     configured = 1;
1358     return 0;
1359 }
1360
1361 /* ------------------------ plugin register / entry point ------------------------ */
1362
1363 /** 
1364  * Plugin "entry" - register all callback.
1365  * 
1366  */
1367 void module_register (void)
1368 {
1369     plugin_register_config ("barometer", 
1370                             collectd_barometer_config, 
1371                             config_keys, 
1372                             config_keys_num);
1373     plugin_register_init ("barometer", collectd_barometer_init);
1374     plugin_register_shutdown ("barometer", collectd_barometer_shutdown);
1375 }