--- /dev/null
+#include "stm32f1xx.h"
+#include "stm32f1xx_hal.h"
+
+#include "util.h"
+#include "app.h"
+
+static uint bmp_read(uint reg, uint bytes)
+{
+ LL_I2C_GenerateStartCondition(I2C1);
+ while (!LL_I2C_IsActiveFlag_SB(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, 0xee);
+ while (!LL_I2C_IsActiveFlag_ADDR(I2C1))
+ ;
+ LL_I2C_ClearFlag_ADDR(I2C2);
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, reg);
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_GenerateStopCondition(I2C1);
+
+ LL_I2C_GenerateStartCondition(I2C1);
+ while (!LL_I2C_IsActiveFlag_SB(I2C1))
+ ;
+ LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_ACK);
+ LL_I2C_TransmitData8(I2C1, 0xef);
+ while (!LL_I2C_IsActiveFlag_ADDR(I2C1))
+ ;
+ LL_I2C_ClearFlag_ADDR(I2C2);
+
+ uint d = 0;
+ for (uint i=0; i<bytes; i++)
+ {
+ if (i == bytes-1)
+ LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
+ while (!LL_I2C_IsActiveFlag_RXNE(I2C1))
+ ;
+ d = (d << 8) | LL_I2C_ReceiveData8(I2C1);
+ }
+
+ LL_I2C_GenerateStopCondition(I2C1);
+ return d;
+}
+
+static uint bmp_start_measure(uint type, uint bytes)
+{
+ LL_I2C_GenerateStartCondition(I2C1);
+ while (!LL_I2C_IsActiveFlag_SB(I2C1))
+ ;
+
+ LL_I2C_TransmitData8(I2C1, 0xee);
+ while (!LL_I2C_IsActiveFlag_ADDR(I2C1))
+ ;
+ LL_I2C_ClearFlag_ADDR(I2C2);
+
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, 0xf4);
+
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_TransmitData8(I2C1, type);
+
+ while (!LL_I2C_IsActiveFlag_TXE(I2C1))
+ ;
+ LL_I2C_GenerateStopCondition(I2C1);
+
+ while (!LL_GPIO_IsInputPinSet(BMP_DONE_GPIO_Port, BMP_DONE_Pin))
+ ;
+
+ return bmp_read(0xf6, bytes);
+}
+
+// Formulae from BMP085 specs
+static void bmp_recalc(uint UT, uint UP, uint oss, u16 cc[11], int *tt, int *pp)
+{
+ s16 AC1 = cc[0];
+ s16 AC2 = cc[1];
+ s16 AC3 = cc[2];
+ u16 AC4 = cc[3];
+ u16 AC5 = cc[4];
+ u16 AC6 = cc[5];
+ s16 B1 = cc[6];
+ s16 B2 = cc[7];
+ s16 MB = cc[8];
+ s16 MC = cc[9];
+ s16 MD = cc[10];
+ UP >>= (8-oss);
+
+ int X1 = (UT-AC6)*AC5 / (1<<15);
+ int X2 = MC*(1<<11) / (X1+MD);
+ int B5 = X1 + X2;
+ int T = (B5+8) / (1<<4);
+ *tt = T;
+
+ int B6 = B5 - 4000;
+ X1 = (B2*(B6*B6/(1<<12))) / (1<<11);
+ X2 = AC2 * B6 / (1<<11);
+ int X3 = X1 + X2;
+ int B3 = (((AC1*4 + X3) << oss) + 2) / 4;
+ X1 = AC3 * B6 / (1<<13);
+ X2 = (B1*(B6*B6/(1<<12))) / (1<<16);
+ X3 = ((X1+X2) + 2) / (1<<2);
+ uint B4 = (uint)(AC4 * (X3 + 32768)) / (1U<<15);
+ uint B7 = (uint)(UP-B3) * (uint)(50000>>oss);
+ int p;
+ if (B7 < 0x80000000)
+ p = (B7*2) / B4;
+ else
+ p = B7 / B4 * 2;
+ X1 = (p/(1<<8)) * (p/(1<<8));
+ X1 = (X1*3038) / (1<<16);
+ X2 = (-7357*p) / (1<<16);
+ p = p + (X1 + X2 + 3791) / (1<<4);
+ *pp = p;
+}
+
+static u16 bmp_constants[11];
+
+void bmp_init(void)
+{
+ for (uint i=0; i<11; i++)
+ bmp_constants[i] = bmp_read(0xaa + 2*i, 2);
+}
+
+#if 0
+void run_test(void)
+{
+ for (;;)
+ {
+ debug_puts("Constants:");
+ u16 cc[11];
+ for (uint i=0; i<11; i++)
+ {
+ cc[i] = bmp_read(0xaa + 2*i, 2);
+ debug_printf(" %04x", cc[i]);
+ }
+ debug_puts("\r\n");
+
+ uint raw_temp = bmp_measure(0x2e, 2);
+ debug_printf("Raw temperature: %04x\r\n", raw_temp);
+
+ uint oss = 3; // Over-sampling setting
+ uint raw_press = bmp_measure(0xf4 | (oss<<6), 3);
+ debug_printf("Raw pressure: %06x\r\n", raw_press);
+
+ int temp, press;
+ bmp_recalc(raw_temp, raw_press, oss, cc, &temp, &press);
+ debug_printf("Temperature: %d ddegC\r\n", temp);
+ debug_printf("Pressure: %d Pa\r\n", press);
+ }
+#endif