7 typedef unsigned int uint;
12 void debug_putc(int c)
14 while (!LL_USART_IsActiveFlag_TXE(USART2))
16 LL_USART_TransmitData8(USART2, c);
19 void debug_puts(const char *s)
33 static void printf_string(const char *s, uint width, uint flags)
36 uint pad = (len < width) ? width - len : 0;
37 char pad_char = (flags & PF_ZERO_PAD) ? '0' : ' ';
43 if (!(flags & PF_LEFT))
47 static void printf_number(uint i, uint width, uint flags, uint base)
50 char *w = buf + sizeof(buf);
52 if (flags & PF_SIGNED)
64 uint digit = i % base;
68 *--w = ((flags & PF_UPPERCASE) ? 'A' : 'a') + digit - 10;
73 if (flags & PF_NEGATIVE)
76 printf_string(w, width, flags);
79 void debug_printf(const char *fmt, ...)
105 flags |= PF_ZERO_PAD;
108 while (*fmt >= '0' && *fmt <= '9')
109 width = 10*width + *fmt++ - '0';
115 printf_number(va_arg(args, int), width, flags | PF_SIGNED, 10);
118 printf_number(va_arg(args, int), width, flags, 10);
121 flags |= PF_UPPERCASE;
124 printf_number(va_arg(args, int), width, flags, 16);
127 printf_string(va_arg(args, char *), width, flags);
140 static uint bmp_read(uint reg, uint bytes)
142 LL_I2C_ClearFlag_STOP(I2C1);
143 LL_I2C_ClearFlag_BERR(I2C1);
144 LL_I2C_HandleTransfer(I2C1, 0xee, LL_I2C_ADDRSLAVE_7BIT, 1, LL_I2C_MODE_SOFTEND, LL_I2C_GENERATE_START_WRITE);
145 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
147 LL_I2C_TransmitData8(I2C1, reg);
148 while (!LL_I2C_IsActiveFlag_TC(I2C1))
150 LL_I2C_HandleTransfer(I2C1, 0xef, LL_I2C_ADDRSLAVE_7BIT, bytes, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_RESTART_7BIT_READ);
153 for (uint i=0; i<bytes; i++)
155 while (!LL_I2C_IsActiveFlag_RXNE(I2C1))
157 d = (d << 8) | LL_I2C_ReceiveData8(I2C1);
163 static uint bmp_measure(uint type, uint bytes)
165 LL_I2C_HandleTransfer(I2C1, 0xee, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
166 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
168 LL_I2C_TransmitData8(I2C1, 0xf4);
169 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
171 LL_I2C_TransmitData8(I2C1, type);
172 while (!LL_I2C_IsActiveFlag_STOP(I2C1))
175 while (!LL_GPIO_IsInputPinSet(BMP_DONE_GPIO_Port, BMP_DONE_Pin))
178 return bmp_read(0xf6, bytes);
181 // Formulae from BMP085 specs
182 void bmp_recalc(uint UT, uint UP, uint oss, u16 cc[11], int *tt, int *pp)
197 int X1 = (UT-AC6)*AC5 / (1<<15);
198 int X2 = MC*(1<<11) / (X1+MD);
200 int T = (B5+8) / (1<<4);
204 X1 = (B2*(B6*B6/(1<<12))) / (1<<11);
205 X2 = AC2 * B6 / (1<<11);
207 int B3 = (((AC1*4 + X3) << oss) + 2) / 4;
208 X1 = AC3 * B6 / (1<<13);
209 X2 = (B1*(B6*B6/(1<<12))) / (1<<16);
210 X3 = ((X1+X2) + 2) / (1<<2);
211 uint B4 = (uint)(AC4 * (X3 + 32768)) / (1U<<15);
212 uint B7 = (uint)(UP-B3) * (uint)(50000>>oss);
218 X1 = (p/(1<<8)) * (p/(1<<8));
219 X1 = (X1*3038) / (1<<16);
220 X2 = (-7357*p) / (1<<16);
221 p = p + (X1 + X2 + 3791) / (1<<4);
229 LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
231 debug_puts("Constants:");
233 for (uint i=0; i<11; i++)
235 cc[i] = bmp_read(0xaa + 2*i, 2);
236 debug_printf(" %04x", cc[i]);
240 uint raw_temp = bmp_measure(0x2e, 2);
241 debug_printf("Raw temperature: %04x\r\n", raw_temp);
243 uint oss = 3; // Over-sampling setting
244 uint raw_press = bmp_measure(0xf4 | (oss<<6), 3);
245 debug_printf("Raw pressure: %06x\r\n", raw_press);
248 bmp_recalc(raw_temp, raw_press, oss, cc, &temp, &press);
249 debug_printf("Temperature: %d ddegC\r\n", temp);
250 debug_printf("Pressure: %d Pa\r\n", press);
258 // Based on https://github.com/adafruit/Adafruit_SSD1306
260 #define SSD1306_SETLOWCOLUMN 0x00
261 #define SSD1306_SETHIGHCOLUMN 0x10
262 #define SSD1306_MEMORYMODE 0x20
263 #define SSD1306_SETSTARTLINE 0x40
264 #define SSD1306_SETCONTRAST 0x81
265 #define SSD1306_CHARGEPUMP 0x8D
266 #define SSD1306_SEGREMAP 0xA0
267 #define SSD1306_DISPLAYALLON_RESUME 0xA4
268 #define SSD1306_DISPLAYALLON 0xA5
269 #define SSD1306_NORMALDISPLAY 0xA6
270 #define SSD1306_INVERTDISPLAY 0xA7
271 #define SSD1306_SETMULTIPLEX 0xA8
272 #define SSD1306_DISPLAYOFF 0xAE
273 #define SSD1306_DISPLAYON 0xAF
274 #define SSD1306_SETSTARTPAGE 0xB0
275 #define SSD1306_COMSCANINC 0xC0
276 #define SSD1306_COMSCANDEC 0xC8
277 #define SSD1306_SETDISPLAYOFFSET 0xD3
278 #define SSD1306_SETCOMPINS 0xDA
279 #define SSD1306_SETVCOMDETECT 0xDB
280 #define SSD1306_SETDISPLAYCLOCKDIV 0xD5
281 #define SSD1306_SETPRECHARGE 0xD9
282 #define SSD1306_NOP 0xE3
284 static const byte display_init_cmds[] = {
286 SSD1306_SETDISPLAYCLOCKDIV, 0x80, // the suggested ratio 0x80
287 SSD1306_SETMULTIPLEX, 0x1F, // ratio 32
288 SSD1306_SETDISPLAYOFFSET,0x0, // no offset
289 SSD1306_SETSTARTLINE | 0x0, // line #0
290 SSD1306_CHARGEPUMP, 0x14, // internal vcc
291 SSD1306_MEMORYMODE, 0x02, // page mode
292 SSD1306_SEGREMAP | 0x0, // column 0 mapped to SEG0
293 SSD1306_COMSCANDEC, // column scan direction reversed
294 SSD1306_SETCOMPINS, 0x02, // sequential COM pins, disable remap
295 SSD1306_SETCONTRAST, 0x7F, // contrast level 127
296 SSD1306_SETPRECHARGE, 0xF1, // pre-charge period (1, 15)
297 SSD1306_SETVCOMDETECT, 0x40, // vcomh regulator level-
298 SSD1306_DISPLAYALLON_RESUME,
299 SSD1306_NORMALDISPLAY,
303 static void display_cmd(byte cmd)
305 LL_I2C_ClearFlag_STOP(I2C1);
306 LL_I2C_HandleTransfer(I2C1, 0x79, LL_I2C_ADDRSLAVE_7BIT, 2, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
307 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
309 LL_I2C_TransmitData8(I2C1, 0x00); // Will send a command
310 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
312 LL_I2C_TransmitData8(I2C1, cmd);
313 while (!LL_I2C_IsActiveFlag_STOP(I2C1))
317 static void display_data_start(uint cnt)
319 LL_I2C_ClearFlag_STOP(I2C1);
320 LL_I2C_HandleTransfer(I2C1, 0x79, LL_I2C_ADDRSLAVE_7BIT, cnt + 1, LL_I2C_MODE_AUTOEND, LL_I2C_GENERATE_START_WRITE);
321 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
323 LL_I2C_TransmitData8(I2C1, 0x40); // Will send data
326 static void display_data(byte d)
328 while (!LL_I2C_IsActiveFlag_TXE(I2C1))
330 LL_I2C_TransmitData8(I2C1, d);
333 static void display_data_end(void)
335 while (!LL_I2C_IsActiveFlag_STOP(I2C1))
339 static void display_init(void)
341 for (uint i=0; i < sizeof(display_init_cmds); i++)
342 display_cmd(display_init_cmds[i]);
344 for (uint p=0; p<4; p++)
346 display_cmd(SSD1306_SETSTARTPAGE + p);
347 display_cmd(SSD1306_SETHIGHCOLUMN);
348 display_cmd(SSD1306_SETLOWCOLUMN);
349 display_data_start(128);
350 for (uint i=0; i<128; i++)
351 display_data(p == 0 ? 0x80 | i : 0);
360 debug_puts("Init\r\n");
365 LL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
367 debug_printf("Tick tock: %d\r\n", cnt);