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