]> mj.ucw.cz Git - home-hw.git/blob - Src/test.c
BMP085 temperature and pressure readings
[home-hw.git] / Src / test.c
1 #include "main.h"
2
3 #include <stdarg.h>
4 #include <stdint.h>
5 #include <string.h>
6
7 typedef unsigned int uint;
8 typedef uint16_t u16;
9 typedef int16_t s16;
10
11 void debug_putc(int c)
12 {
13   while (!LL_USART_IsActiveFlag_TXE(USART2))
14     ;
15   LL_USART_TransmitData8(USART2, c);
16 }
17
18 void debug_puts(const char *s)
19 {
20   while (*s)
21     debug_putc(*s++);
22 }
23
24 enum printf_flags {
25   PF_ZERO_PAD = 1,
26   PF_SIGNED = 2,
27   PF_NEGATIVE = 4,
28   PF_UPPERCASE = 8,
29   PF_LEFT = 16,
30 };
31
32 static void printf_string(const char *s, uint width, uint flags)
33 {
34   uint len = strlen(s);
35   uint pad = (len < width) ? width - len : 0;
36   char pad_char = (flags & PF_ZERO_PAD) ? '0' : ' ';
37
38   if (flags & PF_LEFT)
39     debug_puts(s);
40   while (pad--)
41     debug_putc(pad_char);
42   if (!(flags & PF_LEFT))
43     debug_puts(s);
44 }
45
46 static void printf_number(uint i, uint width, uint flags, uint base)
47 {
48   char buf[16];
49   char *w = buf + sizeof(buf);
50
51   if (flags & PF_SIGNED)
52     {
53       if ((int) i < 0)
54         {
55           i = - (int) i;
56           flags |= PF_NEGATIVE;
57         }
58     }
59
60   *--w = 0;
61   do
62     {
63       uint digit = i % base;
64       if (digit < 10)
65         *--w = '0' + digit;
66       else
67         *--w = ((flags & PF_UPPERCASE) ? 'A' : 'a') + digit - 10;
68       i /= base;
69     }
70   while (i);
71
72   if (flags & PF_NEGATIVE)
73     *--w = '-';
74
75   printf_string(w, width, flags);
76 }
77
78 void debug_printf(const char *fmt, ...)
79 {
80   va_list args;
81   va_start(args, fmt);
82
83   while (*fmt)
84     {
85       int c = *fmt++;
86       if (c != '%')
87         {
88           debug_putc(c);
89           continue;
90         }
91
92       uint width = 0;
93       uint flags = 0;
94
95       if (*fmt == '-')
96         {
97           fmt++;
98           flags |= PF_LEFT;
99         }
100
101       if (*fmt == '0')
102         {
103           fmt++;
104           flags |= PF_ZERO_PAD;
105         }
106
107       while (*fmt >= '0' && *fmt <= '9')
108         width = 10*width + *fmt++ - '0';
109
110       c = *fmt++;
111       switch (c)
112         {
113         case 'd':
114           printf_number(va_arg(args, int), width, flags | PF_SIGNED, 10);
115           break;
116         case 'u':
117           printf_number(va_arg(args, int), width, flags, 10);
118           break;
119         case 'X':
120           flags |= PF_UPPERCASE;
121           // fall-thru
122         case 'x':
123           printf_number(va_arg(args, int), width, flags, 16);
124           break;
125         case 's':
126           printf_string(va_arg(args, char *), width, flags);
127           break;
128         default:
129           debug_putc(c);
130           continue;
131         }
132     }
133
134   va_end(args);
135 }
136
137 static uint bmp_read(uint reg, uint bytes)
138 {
139   LL_I2C_ClearFlag_STOP(I2C1);
140   LL_I2C_ClearFlag_BERR(I2C1);
141   LL_I2C_HandleTransfer(I2C1, 0xee, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
142   while (!LL_I2C_IsActiveFlag_TXE(I2C1))
143     ;
144   LL_I2C_TransmitData8(I2C1, reg);
145   while (!LL_I2C_IsActiveFlag_TC(I2C1))
146     ;
147   LL_I2C_HandleTransfer(I2C1, 0xef, LL_I2C_ADDRSLAVE_7BIT, bytes, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ);
148
149   uint d = 0;
150   for (uint i=0; i<bytes; i++)
151     {
152       while (!LL_I2C_IsActiveFlag_RXNE(I2C1))
153         ;
154       d = (d << 8) | LL_I2C_ReceiveData8(I2C1);
155     }
156
157   return d;
158 }
159
160 static uint bmp_measure(uint type, uint bytes)
161 {
162   LL_I2C_HandleTransfer(I2C1, 0xee, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
163   while (!LL_I2C_IsActiveFlag_TXE(I2C1))
164     ;
165   LL_I2C_TransmitData8(I2C1, 0xf4);
166   while (!LL_I2C_IsActiveFlag_TXE(I2C1))
167     ;
168   LL_I2C_TransmitData8(I2C1, type);
169   while (!LL_I2C_IsActiveFlag_STOP(I2C1))
170     ;
171
172   while (!LL_GPIO_IsInputPinSet(BMP_DONE_GPIO_Port, BMP_DONE_Pin))
173     ;
174
175   return bmp_read(0xf6, bytes);
176 }
177
178 // Formulae from BMP085 specs
179 void bmp_recalc(uint UT, uint UP, uint oss, u16 cc[11], int *tt, int *pp)
180 {
181   s16 AC1 = cc[0];
182   s16 AC2 = cc[1];
183   s16 AC3 = cc[2];
184   u16 AC4 = cc[3];
185   u16 AC5 = cc[4];
186   u16 AC6 = cc[5];
187   s16 B1 = cc[6];
188   s16 B2 = cc[7];
189   s16 MB = cc[8];
190   s16 MC = cc[9];
191   s16 MD = cc[10];
192   UP >>= (8-oss);
193
194   int X1 = (UT-AC6)*AC5 / (1<<15);
195   int X2 = MC*(1<<11) / (X1+MD);
196   int B5 = X1 + X2;
197   int T = (B5+8) / (1<<4);
198   *tt = T;
199
200   int B6 = B5 - 4000;
201   X1 = (B2*(B6*B6/(1<<12))) / (1<<11);
202   X2 = AC2 * B6 / (1<<11);
203   int X3 = X1 + X2;
204   int B3 = (((AC1*4 + X3) << oss) + 2) / 4;
205   X1 = AC3 * B6 / (1<<13);
206   X2 = (B1*(B6*B6/(1<<12))) / (1<<16);
207   X3 = ((X1+X2) + 2) / (1<<2);
208   uint B4 = (uint)(AC4 * (X3 + 32768)) / (1U<<15);
209   uint B7 = (uint)(UP-B3) * (uint)(50000>>oss);
210   int p;
211   if (B7 < 0x80000000)
212     p = (B7*2) / B4;
213   else
214     p = B7 / B4 * 2;
215   X1 = (p/(1<<8)) * (p/(1<<8));
216   X1 = (X1*3038) / (1<<16);
217   X2 = (-7357*p) / (1<<16);
218   p = p + (X1 + X2 + 3791) / (1<<4);
219   *pp = p;
220 }
221
222 void run_test(void)
223 {
224   for (;;)
225     {
226       LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
227
228       debug_puts("Constants:");
229       u16 cc[11];
230       for (uint i=0; i<11; i++)
231         {
232           cc[i] = bmp_read(0xaa + 2*i, 2);
233           debug_printf(" %04x", cc[i]);
234         }
235       debug_puts("\r\n");
236
237       uint raw_temp = bmp_measure(0x2e, 2);
238       debug_printf("Raw temperature: %04x\r\n", raw_temp);
239
240       uint oss = 3;     // Over-sampling setting
241       uint raw_press = bmp_measure(0xf4 | (oss<<6), 3);
242       debug_printf("Raw pressure: %06x\r\n", raw_press);
243
244       int temp, press;
245       bmp_recalc(raw_temp, raw_press, oss, cc, &temp, &press);
246       debug_printf("Temperature: %d ddegC\r\n", temp);
247       debug_printf("Pressure: %d Pa\r\n", press);
248
249       LL_mDelay(1000);
250     }
251 }