Wrote part of the BMP280 driver, temperature reading is working, added bosch BMA456 driver with wrist tilt detection feature working, added missing burst write in the i2c driver

This commit is contained in:
Th3maz1ng 2022-12-23 23:21:38 +01:00
parent ba885b52b9
commit 4ab0768ae5
10 changed files with 12400 additions and 16 deletions

View File

@ -0,0 +1,145 @@
#include <math.h>
#include "i2c.h"
#include "BMP280.h"
#include "wm_osal.h"
#include "FreeRTOS.h"
typedef struct
{
uint16_t dig_T1;
int16_t dig_T2;
int16_t dig_T3;
uint16_t dig_P1;
int16_t dig_P2;
int16_t dig_P3;
int16_t dig_P4;
int16_t dig_P5;
int16_t dig_P6;
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
} BMP280_calibration_data;
static BMP280_calibration_data _calibration_data = {0};
static BMP280_Mode_e _mode;
static int32_t t_fine = 0;
static bool _BMP280_read_calibration_data(void)
{
uint8_t data[2];
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_T1, data, sizeof data))
_calibration_data.dig_T1 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_T2, data, sizeof data))
_calibration_data.dig_T2 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_T3, data, sizeof data))
_calibration_data.dig_T3 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P1, data, sizeof data))
_calibration_data.dig_P1 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P2, data, sizeof data))
_calibration_data.dig_P2 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P3, data, sizeof data))
_calibration_data.dig_P3 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P4, data, sizeof data))
_calibration_data.dig_P4 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P5, data, sizeof data))
_calibration_data.dig_P5 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P6, data, sizeof data))
_calibration_data.dig_P6 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P7, data, sizeof data))
_calibration_data.dig_P7 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P8, data, sizeof data))
_calibration_data.dig_P8 = data[1] << 8 | data[0];
else return false;
if(i2c_read(BMP280_I2C_ADDR, BMP280_DIG_P9, data, sizeof data))
_calibration_data.dig_P9 = data[1] << 8 | data[0];
else return false;
return true;
}
bool BMP280_init(void)
{
uint8_t data;
if(!i2c_read_reg(BMP280_I2C_ADDR, BMP280_ID_REG, &data)) return false;
if(data != BMP280_ID) return false;
if(!_BMP280_read_calibration_data())
return false;
return true;
}
bool BMP280_configure(BMP280_Mode_e mode, BMP280_Oversampling_e temperature_oversampling, BMP280_Oversampling_e pressure_oversampling, BMP280_Filter_e filter, BMP280_Standby_Duration_e standby_duration)
{
_mode = mode;
if(!i2c_write_reg(BMP280_I2C_ADDR, BMP280_CONFIG, standby_duration << 5 | filter << 2)) return false;
tls_os_time_delay(pdMS_TO_TICKS(4)); //Ugly but needed :(
return i2c_write_reg(BMP280_I2C_ADDR, BMP280_CTRL_MEAS, temperature_oversampling << 5 | pressure_oversampling << 2 | mode);
}
bool BMP280_trigger_measurement(void)
{
uint8_t data;
if(!i2c_read_reg(BMP280_I2C_ADDR, BMP280_CTRL_MEAS, &data)) return false;
data &= 0xFC;
data |= _mode;
return i2c_write_reg(BMP280_I2C_ADDR, BMP280_CTRL_MEAS, data);
}
float BMP280_get_temperature(void)
{
int32_t var1, var2;
uint8_t data[3];
if(!i2c_read(BMP280_I2C_ADDR, BMP280_TEMP_MSB, data, sizeof data)) return 0.0f;
int32_t adc_T = data[0] << 16 | data[1] << 8 | data[2];
adc_T >>= 4;
var1 = ((((adc_T >> 3) - ((int32_t)_calibration_data.dig_T1 << 1))) *
((int32_t)_calibration_data.dig_T2)) >>
11;
var2 = (((((adc_T >> 4) - ((int32_t)_calibration_data.dig_T1)) *
((adc_T >> 4) - ((int32_t)_calibration_data.dig_T1))) >>
12) *
((int32_t)_calibration_data.dig_T3)) >>
14;
t_fine = var1 + var2;
float T = (t_fine * 5 + 128) >> 8;
return T / 100;
}
bool BMP280_software_reset(void)
{
return false;
}

View File

@ -1,6 +1,90 @@
#ifndef BMP280_H
#define BMP280_H
/* Device i2c address */
#define BMP280_I2C_ADDR 0x76
/* Device ID */
#define BMP280_ID 0x58
/* Device registers list */
#define BMP280_TEMP_XLSB 0xFC
#define BMP280_TEMP_LSB 0xFB
#define BMP280_TEMP_MSB 0xFA
#define BMP280_PRESS_XLSB 0xF9
#define BMP280_PRESS_LSB 0xF8
#define BMP280_PRESS_MSB 0xF7
#define BMP280_CONFIG 0xF5
#define BMP280_CTRL_MEAS 0xF4
#define BMP280_STATUS 0xF3
#define BMP280_RESET 0xE0
#define BMP280_ID_REG 0xD0
/* Device calibration registers list */
#define BMP280_DIG_T1 0x88
#define BMP280_DIG_T2 0x8A
#define BMP280_DIG_T3 0x8C
#define BMP280_DIG_P1 0x8E
#define BMP280_DIG_P2 0x90
#define BMP280_DIG_P3 0x92
#define BMP280_DIG_P4 0x94
#define BMP280_DIG_P5 0x96
#define BMP280_DIG_P6 0x98
#define BMP280_DIG_P7 0x9A
#define BMP280_DIG_P8 0x9C
#define BMP280_DIG_P9 0x9E
/* Field masks */
/* Configuration enumerations */
typedef enum
{
BMP280_Sleep = 0,
BMP280_Forced = 1,
BMP280_Normal = 3,
} BMP280_Mode_e;
typedef enum
{
BMP280_Oversampling_Skipped = 0,
BMP280_Oversampling_x1 = 1,
BMP280_Oversampling_x2 = 2,
BMP280_Oversampling_x4 = 3,
BMP280_Oversampling_x8 = 4,
BMP280_Oversampling_x16 = 5,
} BMP280_Oversampling_e;
typedef enum
{
BMP280_Filter_OFF = 0,
BMP280_Filter_x2 = 1,
BMP280_Filter_x4 = 2,
BMP280_Filter_x8 = 3,
BMP280_Filter_x16 = 4,
} BMP280_Filter_e;
typedef enum
{
BMP280_Standby_0_5MS = 0,
BMP280_Standby_62_5MS = 1,
BMP280_Standby_125MS = 2,
BMP280_Standby_250MS = 3,
BMP280_Standby_500MS = 4,
BMP280_Standby_1000MS = 5,
BMP280_Standby_2000MS = 6,
BMP280_Standby_4000MS = 7,
} BMP280_Standby_Duration_e;
bool BMP280_init(void);
bool BMP280_configure(BMP280_Mode_e mode, BMP280_Oversampling_e temperature_oversampling, BMP280_Oversampling_e pressure_oversampling, BMP280_Filter_e filter, BMP280_Standby_Duration_e standby_duration);
bool BMP280_trigger_measurement(void);
float BMP280_get_temperature(void);
bool BMP280_software_reset(void);
#endif //BMP280_H

View File

@ -11,9 +11,9 @@ typedef struct
int16_t z_min;
int16_t z_max;
float temperature_offset;
} _QMC5883L_calibration_data;
} QMC5883L_calibration_data;
static _QMC5883L_calibration_data calibration_data = {0};
static QMC5883L_calibration_data _calibration_data = {0};
bool QMC5883L_init(void)
@ -39,7 +39,7 @@ float QMC5883L_get_temperature(void)
raw_temp |= data;
return (float) raw_temp / 100.0 + calibration_data.temperature_offset;
return (float) raw_temp / 100.0 + _calibration_data.temperature_offset;
}
bool QMC5883L_is_data_available(void)
@ -53,13 +53,13 @@ bool QMC5883L_is_data_available(void)
void QMC5883L_set_calibration_data(int16_t x_min, int16_t x_max, int16_t y_min, int16_t y_max, int16_t z_min, int16_t z_max, float temperature_offset)
{
calibration_data.x_min = x_min;
calibration_data.x_max = x_max;
calibration_data.y_min = y_min;
calibration_data.y_max = y_max;
calibration_data.z_min = z_min;
calibration_data.z_max = z_max;
calibration_data.temperature_offset = temperature_offset;
_calibration_data.x_min = x_min;
_calibration_data.x_max = x_max;
_calibration_data.y_min = y_min;
_calibration_data.y_max = y_max;
_calibration_data.z_min = z_min;
_calibration_data.z_max = z_max;
_calibration_data.temperature_offset = temperature_offset;
}
QMC5883L_MData_t QMC5883L_get_MFields_raw(void)
@ -89,12 +89,12 @@ QMC5883L_MData_calibrated_t QMC5883L_get_MFields_calibrated(void)
Mdata.MFieldZ = (data[5] << 8) | data[4];
}
int x_offset = (calibration_data.x_min + calibration_data.x_max) / 2;
int y_offset = (calibration_data.y_min + calibration_data.y_max) / 2;
int z_offset = (calibration_data.z_min + calibration_data.z_max) / 2;
int x_avg_delta = (calibration_data.x_max - calibration_data.x_min) / 2;
int y_avg_delta = (calibration_data.y_max - calibration_data.y_min) / 2;
int z_avg_delta = (calibration_data.z_max - calibration_data.z_min) / 2;
int x_offset = (_calibration_data.x_min + _calibration_data.x_max) / 2;
int y_offset = (_calibration_data.y_min + _calibration_data.y_max) / 2;
int z_offset = (_calibration_data.z_min + _calibration_data.z_max) / 2;
int x_avg_delta = (_calibration_data.x_max - _calibration_data.x_min) / 2;
int y_avg_delta = (_calibration_data.y_max - _calibration_data.y_min) / 2;
int z_avg_delta = (_calibration_data.z_max - _calibration_data.z_min) / 2;
int avg_delta = (x_avg_delta + y_avg_delta + z_avg_delta) / 3;

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
#include "wm_io.h"
#include "wm_gpio_afsel.h"
#include "wm_i2c.h"
#include "i2c.h"
void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency)
{
@ -10,6 +11,31 @@ void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequen
tls_i2c_init(frequency);
}
bool i2c_write(uint8_t address, uint8_t reg, const uint8_t *const data, size_t length)
{
if(!data) return false;
//First we send the address followed by the register from where we want to start writing:
tls_i2c_write_byte(address << 1, true);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
tls_i2c_write_byte(reg, false);
if(tls_i2c_wait_ack() != WM_SUCCESS) return false;
for(size_t i = 0; i < length; i++)
{
tls_i2c_write_byte(data[i], false);
if(tls_i2c_wait_ack() != WM_SUCCESS)
{
tls_i2c_stop();
return false;
}
}
tls_i2c_stop();
return true;
}
bool i2c_write_reg(uint8_t address, uint8_t reg, uint8_t data)
{
//First we send the address followed by the register we want to write to:

View File

@ -15,6 +15,18 @@
*/
void i2c_init(enum tls_io_name SDAPin, enum tls_io_name SCLPin, uint32_t frequency);
/**
* @brief
*
* @param address the 7 bit address of the slave device
* @param reg the address of the register from where the write will start (the device should have write with autoincrement register functionality)
* @param data a pointer to an array of uint8_t where the data to write is stored
* @param length the size in bytes of the data array
* @return true on success
* @return false on failure
*/
bool i2c_write(uint8_t address, uint8_t reg, const uint8_t * const data, size_t length);
/**
* @brief Writes the given data to the provided register of the slave device.
*