You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

277 lines
7.0 KiB

/*
"THE BEER/MATE-WARE LICENSE":
<xil@xil.se> wrote this file. As long as you retain this notice you
can do whatever you want with this stuff. If we meet some day, and you think
this stuff is worth it, you can buy us a ( > 0 ) beer/mate in return - The Xil TEAM
*/
#include <stdint.h>
#include "drivers/i2c.h"
#include "drivers/bmp180.h"
#include "drivers/drivers.h"
#define I2C_ADDRESS 0x77
#define BMP180_REG_ID 0xD0
#define BMP180_REG_CONTROL 0xF4
#define BMP180_REG_MSB 0xF6
#define BMP180_REG_LSB 0xF7
#define BMP180_REG_XLSB 0xF8
#define BMP180_ID 0x55
#define BMP180_TEMPERATURE 0x2E
#define BMP180_PRESSURE_OSS0 0x34
#define BMP180_PRESSURE_OSS1 0x74
#define BMP180_PRESSURE_OSS2 0xB4
#define BMP180_PRESSURE_OSS3 0xF4
#define BMP180_CONVERSION_TIME_TEMERATURE 4500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS0 4500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS1 7500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS2 13500 // us
#define BMP180_CONVERSION_TIME_PRESSURE_OSS3 25500 // us
static int32_t ICACHE_FLASH_ATTR read24_int(bmp180_t* bmp180, int reg, bool b24)
{
int res;
uint8_t val[3] = {0};
val[0] = reg;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, val, 1);
if (res != 0)
{
return 0;
}
if (b24)
{
res = i2c_receive(bmp180->i2c, I2C_ADDRESS, val, 3);
}
else
{
res = i2c_receive(bmp180->i2c, I2C_ADDRESS, val, 2);
}
if (res != 0)
{
return 0;
}
if (b24)
return (val[0] << 16) | (val[1] << 8) | val[2];
else
return (val[0] << 8) | val[1];
}
static int16_t ICACHE_FLASH_ATTR read16(bmp180_t* bmp180, int reg)
{
return read24_int(bmp180, reg, false);
}
static int32_t ICACHE_FLASH_ATTR read24(bmp180_t* bmp180, int reg)
{
return read24_int(bmp180, reg, true);
}
int16_t ICACHE_FLASH_ATTR bmp180_read_temp_raw(bmp180_t* bmp180)
{
int res;
uint8_t buffer[2];
buffer[0] = BMP180_REG_CONTROL;
buffer[1] = BMP180_TEMPERATURE;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, buffer, 2);
if (res != 0)
{
return 0;
}
I2C_DELAY_US(BMP180_CONVERSION_TIME_TEMERATURE);
return read16(bmp180, BMP180_REG_MSB);
}
int32_t ICACHE_FLASH_ATTR bmp180_read_pressure_raw(bmp180_t* bmp180, uint8_t oss)
{
int res;
int reg;
int delay;
uint8_t buffer[2];
switch (oss) {
case bmp180_pressure_sampling_accuracy_ultra_low_power:
reg = BMP180_PRESSURE_OSS0;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS0;
break;
case bmp180_pressure_sampling_accuracy_standard:
reg = BMP180_PRESSURE_OSS1;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS1;
break;
case bmp180_pressure_sampling_accuracy_high_resolution:
reg = BMP180_PRESSURE_OSS2;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS2;
break;
case bmp180_pressure_sampling_accuracy_ultra_high_resolution:
reg = BMP180_PRESSURE_OSS3;
delay = BMP180_CONVERSION_TIME_PRESSURE_OSS3;
break;
default:
return 0;
}
buffer[0] = BMP180_REG_CONTROL;
buffer[1] = reg;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, buffer, 2);
if (res != 0)
{
return 0;
}
I2C_DELAY_US(delay);
return read24(bmp180, BMP180_REG_MSB) >> (8 - oss);
}
static int16_t ICACHE_FLASH_ATTR bmp180_read_temp(bmp180_t* bmp180)
{
uint16_t temp_raw;
int16_t temp;
int32_t x1;
int32_t x2;
if (!bmp180->initilized) {
return 0;
}
temp_raw = bmp180_read_temp_raw(bmp180);
x1 = (temp_raw - bmp180->ac6) * bmp180->ac5 / (2<<14);
x2 = bmp180->mc * (2<<10) / (x1 + bmp180->md);
bmp180->b5 = x1 + x2;
temp = (bmp180->b5 + 8) / (2<<3);
return temp;
}
static int32_t ICACHE_FLASH_ATTR bmp180_read_pressure(bmp180_t* bmp180)
{
int32_t pressure;
int32_t b6;
int32_t x1;
int32_t x2;
int32_t x3;
int32_t b3;
uint32_t b4;
uint32_t b7;
int32_t p;
uint8_t oss = bmp180->pressure_sampling_accuracy;
if (!bmp180->initilized) {
return 0;
}
pressure = bmp180_read_pressure_raw(bmp180, oss);
b6 = bmp180->b5 - 4000;
x1 = ((int32_t)bmp180->b2 * ((b6 * b6) >> 12)) >> 11;
x2 = ((int32_t)bmp180->ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((((int32_t)bmp180->ac1 << 2) + x3) << oss) + 2) >> 2;
x1 = ((int32_t)bmp180->ac3 * b6) >> 13;
x2 = (int32_t)(bmp180->b1 * ((b6 * b6) >> 12)) >> 16;
x3 = (x1 + x2 + 2) >> 2;
b4 = ((uint32_t)bmp180->ac4 * ((uint32_t)(x3 + 32768)) >> 15);
b7 = (pressure - b3) * (50000 >> oss);
p = b7 < 0x80000000 ? (b7 << 1) / b4 : (b7 / b4) << 1;
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
p = p + ((x1 + x2 + 3791) >> 4);
return p;
}
bool ICACHE_FLASH_ATTR bmp180_read(driver_params_t* params)
{
bmp180_t* bmp180 = &params->bmp180;
bmp180->temperature = bmp180_read_temp(bmp180);
bmp180->pressure = bmp180_read_pressure(bmp180);
return true;
}
bool ICACHE_FLASH_ATTR bmp180_print(driver_params_t* params, driver_print_data_t* print)
{
bmp180_t* bmp180 = &params->bmp180;
print->print_string(print->data, print->index, print->i, "driver", "bmp180");
print->print_value(print->data, print->index, print->i, "temp", &bmp180->temperature, sizeof(bmp180->temperature));
print->print_value(print->data, print->index, print->i, "pressure", &bmp180->pressure, sizeof(bmp180->pressure));
return true;
}
bool ICACHE_FLASH_ATTR bmp180_init(driver_params_t* params, driver_bus_t* bus)
{
bmp180_t* bmp180 = &params->bmp180;
i2c_t* i2c = &bus->params.i2c;
int res;
uint8_t id = 0;
uint8_t buffer[1];
bmp180->initilized = false;
bmp180->i2c = i2c;
buffer[0] = BMP180_REG_ID;
res = i2c_transmit(bmp180->i2c, I2C_ADDRESS, buffer, 1);
if (res != 0)
{
return false;
}
res = i2c_receive(bmp180->i2c, I2C_ADDRESS, &id, 1);
if (res != 0)
{
return false;
}
if (id != BMP180_ID) {
return false;
}
bmp180->ac1 = read16(bmp180, 0xAA);
bmp180->ac2 = read16(bmp180, 0xAC);
bmp180->ac3 = read16(bmp180, 0xAE);
bmp180->ac4 = read16(bmp180, 0xB0);
bmp180->ac5 = read16(bmp180, 0xB2);
bmp180->ac6 = read16(bmp180, 0xB4);
bmp180->b1 = read16(bmp180, 0xB6);
bmp180->b2 = read16(bmp180, 0xB8);
bmp180->mb = read16(bmp180, 0xBA);
bmp180->mc = read16(bmp180, 0xBC);
bmp180->md = read16(bmp180, 0xBE);
bmp180->initilized = true;
return true;
}
// Global variable with function pointers
const driver_sensor_t sensor_bmp180 = {
.init = bmp180_init,
.read = bmp180_read,
.print = bmp180_print,
};