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