Vala bindings and examples added. Minor clean-up in header file
[freerunner-navigation-board:bmp085.git] / userspace / bmp085.c
1 #include <stdio.h>
2 #include <fcntl.h>
3 #include <stdlib.h>
4 #include <unistd.h>
5 #include <time.h>
6
7 #include "i2c-dev.h"
8 #include "bmp085.h"
9
10
11 int msleep(unsigned int msecs)
12 {
13         usleep(msecs*1000);
14 }
15
16 s32 read_calibration_values(struct bmp085_data *data)
17 {
18         u8 tmp[BMP085_CALIBRATION_DATA_LENGTH];
19         s32 status = i2c_smbus_read_i2c_block_data(data->client, BMP085_CALIBRATION_DATA_START,
20                                                    BMP085_CALIBRATION_DATA_LENGTH, tmp);
21
22         struct bmp085_calibration_data *cali = &data->calibration;
23         cali->AC1 =  (tmp[0] <<8) | tmp[1];
24         cali->AC2 =  (tmp[2] <<8) | tmp[3];
25         cali->AC3 =  (tmp[4] <<8) | tmp[5];
26         cali->AC4 =  (tmp[6] <<8) | tmp[7];
27         cali->AC5 =  (tmp[8] <<8) | tmp[9];
28         cali->AC6 = (tmp[10] <<8) | tmp[11];
29
30         /*parameters B1,B2*/
31         cali->B1 =  (tmp[12] <<8) | tmp[13];
32         cali->B2 =  (tmp[14] <<8) | tmp[15];
33
34         /*parameters MB,MC,MD*/
35         cali->MB =  (tmp[16] <<8) | tmp[17];
36         cali->MC =  (tmp[18] <<8) | tmp[19];
37         cali->MD =  (tmp[20] <<8) | tmp[21];
38         return status;
39 }
40
41
42 s32 update_raw_temperature(struct bmp085_data *data)
43 {
44         u16 temperature = 0x00;
45         u8 tmp[2];
46         s32 status = i2c_smbus_write_byte_data(data->client, 0xF4, 0x2E);
47         if (status != 0) {
48                 printf("bmp085: Error while requesting temperature measurement: %d\n", status);
49                 return status;
50         }
51         msleep(5);
52
53         status = i2c_smbus_read_i2c_block_data(data->client, 0xF6, sizeof(tmp), tmp);
54         if (status != sizeof(tmp)) {
55                 printf("bmp085: Error while requesting temperature measurement (II): %d\n", status);
56                 return status;
57         }
58         data->raw_temperature = (tmp[0] << 8) + tmp[1];
59         data->next_temp_measurement = time(NULL)+1;
60 //      printf("temperature: %u\n", temperature);
61         return status;
62 }
63
64 s32 update_raw_pressure(struct bmp085_data *data)
65 {
66         u8 tmp[3];
67         s32 status = 0;
68
69         status = i2c_smbus_write_byte_data(data->client, 0xF4, 0x34 + (data->oversampling_setting<<6));
70         if (status != 0) {
71                 printf("bmp085: Error while requesting pressure measurement.\n");
72                 return status;
73         }
74         msleep(2+(3 << data->oversampling_setting<<1)); /* wait for the end of conversion */
75
76         status = i2c_smbus_read_i2c_block_data(data->client, 0xF6, sizeof(tmp), tmp);
77         if (status != sizeof(tmp)) {
78                 printf("bmp085: Error while requesting pressure measurement (II): %d\n", status);
79                 return status;
80         }
81         /* swap positions to correct the MSB/LSB positions */
82         data->raw_pressure = (tmp[0] << 16) | (tmp[1] << 8) | tmp[2];
83         data->raw_pressure = data->raw_pressure >> (8-data->oversampling_setting);
84         return status;
85 }
86
87
88 s32 get_temperature(struct bmp085_data *data)
89 {
90         if (data->next_temp_measurement+1 < time(NULL)) {
91                 update_raw_temperature(data);
92         }
93
94         struct bmp085_calibration_data *cali = &data->calibration;
95         long x1 = ((data->raw_temperature - cali->AC6) * cali->AC5) >> 15;
96         long x2 = (cali->MC << 11) / (x1 + cali->MD);
97         data->b6 = x1 + x2 - 4000;
98 //      printf("got raw temp: %ld; AC5: %d, AC6: %d, MC: %d, MD: %d\n", data->raw_temperature, cali->AC5, cali->AC6, cali->MC, cali->MD);
99         return ((x1+x2+8) >> 4);
100 }
101
102
103 s32 get_pressure(struct bmp085_data *data)
104 {
105         struct bmp085_calibration_data *cali = &data->calibration;
106         long x1, x2, x3, b3;
107         unsigned long b4, b7;
108         long p;
109
110         if (data->next_temp_measurement+1 < time(NULL)) {
111                 get_temperature(data);
112         }
113         update_raw_pressure(data);
114
115 //      printf("raw_pressure: %ud, B6: %ld\n", data->raw_pressure, data->b6);
116
117         x1 = (data->b6 * data->b6) >> 12;
118         x1 *= cali->B2;
119         x1 >>= 11;
120
121         x2 = cali->AC2 * data->b6;
122         x2 >>= 11;
123
124         x3 = x1 + x2;
125
126         b3 = (((((long)cali->AC1) * 4 + x3) << data->oversampling_setting) + 2) >> 2;
127
128 //      printf("x1: %ld, x2: %ld, x3: %ld, b3: %ld\n", x1, x2, x3, b3);
129         x1 = (cali->AC3 * data->b6) >> 13;
130         x2 = (cali->B1 * ((data->b6 * data->b6) >> 12)) >> 16;
131         x3 = (x1 + x2 + 2) >> 2;
132         b4 = (cali->AC4 * (unsigned long)(x3 + 32768)) >> 15;
133
134 //      printf("x1: %ld, x2: %ld, x3: %ld, b4: %ld\n", x1, x2, x3, b4);
135         b7 = ((unsigned long)data->raw_pressure - b3) * (50000 >> data->oversampling_setting);
136         p = ((b7 < 0x80000000) ? ((b7 << 1) / b4) : ((b7 / b4) * 2));
137
138         x1 = p >> 8;
139         x1 *= x1;
140         x1 = (x1 * 3038) >> 16;
141         x2 = (-7357 * p) >> 16;
142         p += (x1 + x2 + 3791) >> 4;
143         return p;
144 }
145
146
147 void set_oversampling(struct bmp085_data *data, unsigned char oversampling)
148 {
149         data->oversampling_setting = oversampling;
150 }
151
152
153 unsigned char get_oversampling(struct bmp085_data *data)
154 {
155         return data->oversampling_setting;
156 }
157
158
159 int open_bmp085(int adapter_nr, struct bmp085_data *data)
160 {
161         char filename[20];
162
163         data->oversampling_setting = 0x03;
164
165         snprintf(filename, 19, "/dev/i2c-%d", adapter_nr);
166         data->client = open(filename, O_RDWR);
167         if (data->client < 0) {
168                 /* ERROR HANDLING; you can check errno to see what went wrong */
169                 return(-1);
170         }
171
172         if (ioctl(data->client, I2C_SLAVE, BMP085_I2C_ADDRESS) < 0) {
173                 /* ERROR HANDLING; you can check errno to see what went wrong */
174                 return(-1);
175         }
176
177         read_calibration_values(data);
178 }
179
180
181 void close_bmp085(struct bmp085_data *data)
182 {
183         close(data->client);
184 }
185
186
187
188 /*
189 int main(void)
190 {
191         struct bmp085_data data;
192         open_bmp085(0x00, &data);
193
194         int temp = get_temperature(&data);
195         int pressure = get_pressure(&data);
196
197         printf("p: %fhPa\tt: %fC\n", pressure/100.0, temp/10.0);
198
199         close_bmp085(&data);
200 }
201 */