]> mj.ucw.cz Git - home-hw.git/blob - Src/bmp085.c
d150b90fb5cfdd25faee56be2935321464184848
[home-hw.git] / Src / bmp085.c
1 #include "stm32f1xx.h"
2 #include "stm32f1xx_hal.h"
3
4 #include "util.h"
5 #include "app.h"
6
7 static byte bmp_i2c_buf[4];
8 volatile byte *bmp_i2c_ptr;
9 volatile byte bmp_i2c_len;
10 volatile byte bmp_i2c_addr;
11
12 static uint bmp_read(uint reg, uint bytes)
13 {
14   bmp_i2c_buf[0] = reg;
15   bmp_i2c_ptr = bmp_i2c_buf;
16   bmp_i2c_len = 1;
17   bmp_i2c_addr = 0xee;
18
19   LL_I2C_GenerateStartCondition(I2C1);
20   LL_I2C_EnableIT_TX(I2C1);
21
22   while (bmp_i2c_len)
23     ;
24
25   bmp_i2c_ptr = bmp_i2c_buf;
26   bmp_i2c_len = bytes;
27   bmp_i2c_addr = 0xef;
28
29   LL_I2C_GenerateStartCondition(I2C1);
30   LL_I2C_EnableIT_RX(I2C1);
31
32   while (bmp_i2c_len)
33     ;
34
35   uint d = 0;
36   for (uint i=0; i<bytes; i++)
37     d = (d << 8) | bmp_i2c_buf[i];
38
39   return d;
40 }
41
42 static void bmp_start_measure(uint type)
43 {
44   LL_I2C_GenerateStartCondition(I2C1);
45   while (!LL_I2C_IsActiveFlag_SB(I2C1))
46     ;
47
48   LL_I2C_TransmitData8(I2C1, 0xee);
49   while (!LL_I2C_IsActiveFlag_ADDR(I2C1))
50     ;
51   LL_I2C_ClearFlag_ADDR(I2C1);
52
53   while (!LL_I2C_IsActiveFlag_TXE(I2C1))
54     ;
55   LL_I2C_TransmitData8(I2C1, 0xf4);
56
57   while (!LL_I2C_IsActiveFlag_TXE(I2C1))
58     ;
59   LL_I2C_TransmitData8(I2C1, type);
60
61   while (!LL_I2C_IsActiveFlag_TXE(I2C1))
62     ;
63   LL_I2C_GenerateStopCondition(I2C1);
64 }
65
66 // Formulae from BMP085 specs
67 static void bmp_recalc(uint UT, uint UP, uint oss, u16 cc[11], s16 *tt, s16 *pp)
68 {
69   s16 AC1 = cc[0];
70   s16 AC2 = cc[1];
71   s16 AC3 = cc[2];
72   u16 AC4 = cc[3];
73   u16 AC5 = cc[4];
74   u16 AC6 = cc[5];
75   s16 B1 = cc[6];
76   s16 B2 = cc[7];
77   // FIXME: Why is this unused?
78   // s16 MB = cc[8];
79   s16 MC = cc[9];
80   s16 MD = cc[10];
81   UP >>= (8-oss);
82
83   int X1 = (UT-AC6)*AC5 / (1<<15);
84   int X2 = MC*(1<<11) / (X1+MD);
85   int B5 = X1 + X2;
86   int T = (B5+8) / (1<<4);
87   *tt = T;
88
89   int B6 = B5 - 4000;
90   X1 = (B2*(B6*B6/(1<<12))) / (1<<11);
91   X2 = AC2 * B6 / (1<<11);
92   int X3 = X1 + X2;
93   int B3 = (((AC1*4 + X3) << oss) + 2) / 4;
94   X1 = AC3 * B6 / (1<<13);
95   X2 = (B1*(B6*B6/(1<<12))) / (1<<16);
96   X3 = ((X1+X2) + 2) / (1<<2);
97   uint B4 = (uint)(AC4 * (X3 + 32768)) / (1U<<15);
98   uint B7 = (uint)(UP-B3) * (uint)(50000>>oss);
99   int p;
100   if (B7 < 0x80000000)
101     p = (B7*2) / B4;
102   else
103     p = B7 / B4 * 2;
104   X1 = (p/(1<<8)) * (p/(1<<8));
105   X1 = (X1*3038) / (1<<16);
106   X2 = (-7357*p) / (1<<16);
107   p = p + (X1 + X2 + 3791) / (1<<4);
108   *pp = p;
109 }
110
111 static u16 bmp_constants[11];
112
113 void bmp_init(void)
114 {
115   for (uint i=0; i<11; i++)
116     {
117       bmp_constants[i] = bmp_read(0xaa + 2*i, 2);
118       debug_printf("BMP: const[%d] = %u\n", i, bmp_constants[i]);
119     }
120 }
121
122 enum bmp_state {
123   BMP_IDLE,
124   BMP_TEMP,
125   BMP_PRESSURE,
126 };
127
128 static byte bmp_state = BMP_IDLE;
129 static u16 raw_temp;
130 static u32 raw_press;
131 #define BMP_OSS 3
132 s16 adjusted_temp;
133 s16 adjusted_press;
134
135 void bmp_step(void)
136 {
137   switch (bmp_state)
138     {
139     case BMP_IDLE:
140       debug_puts("BMP: Start measure\n");
141       bmp_start_measure(0x2e);
142       bmp_state++;
143       break;
144     case BMP_TEMP:
145       if (!LL_GPIO_IsInputPinSet(BMP_DONE_GPIO_Port, BMP_DONE_Pin))
146         return;
147       debug_puts("BMP: Temperature measured\n");
148       raw_temp = bmp_read(0xf6, 2);
149       debug_printf("BMP: Temperature read: %u\n", raw_temp);
150       bmp_start_measure(0xf4 | (BMP_OSS<<6));
151       bmp_state++;
152       break;
153     case BMP_PRESSURE:
154       if (!LL_GPIO_IsInputPinSet(BMP_DONE_GPIO_Port, BMP_DONE_Pin))
155         return;
156       debug_puts("BMP: Pressure measured\n");
157       raw_press = bmp_read(0xf6, 3);
158       debug_printf("BMP: Pressure read: %u\n", raw_press);
159       bmp_recalc(raw_temp, raw_press, BMP_OSS, bmp_constants, &adjusted_temp, &adjusted_press);
160       debug_printf("BMP: Adjusted temp %u, press %u\n", adjusted_temp, adjusted_press);
161       bmp_state = BMP_IDLE;
162       break;
163     }
164 }