diff --git a/CMakeLists.txt b/CMakeLists.txt index 2178ab4..4a986d9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,12 +8,14 @@ set(IMSENSORS_SRCS "src/als/als_ltr_303als.c" "src/dht/dht_aht10.c" "src/dht/dht_bme280.c" + "src/imu/imu_lsm6dsl.c" ) set(IMSENSORS_INCS "include/imsensors/common" "include/imsensors/als" "include/imsensors/dht" + "include/imsensors/imu" ) set(IMSENSORS_INTF_INCS diff --git a/include/imsensors/common/sensors_common.h b/include/imsensors/common/sensors_common.h index 44da229..358c2a2 100644 --- a/include/imsensors/common/sensors_common.h +++ b/include/imsensors/common/sensors_common.h @@ -4,6 +4,7 @@ #include #include #include +#include typedef enum { IMS_SUCCESS, diff --git a/include/imsensors/dht/dht_bme280.h b/include/imsensors/dht/dht_bme280.h index 27280f0..e8f0e3e 100644 --- a/include/imsensors/dht/dht_bme280.h +++ b/include/imsensors/dht/dht_bme280.h @@ -70,11 +70,10 @@ typedef struct { double humidity; } ims_bme280_result_t; #else -/* Result is multiplied by 10000. */ typedef struct { - int32_t temperature; - uint32_t pressure; - int32_t humidity; + int32_t temperature; /* Temperature (C), multiplied by 100. */ + uint32_t pressure; /* Humidity (%), multiplied by 1024. */ + int32_t humidity; /* Pressure (Pa) multiplied by 256. */ } ims_bme280_result_t; #endif diff --git a/include/imsensors/imu/imu_lsm6dsl.h b/include/imsensors/imu/imu_lsm6dsl.h new file mode 100644 index 0000000..2654a70 --- /dev/null +++ b/include/imsensors/imu/imu_lsm6dsl.h @@ -0,0 +1,19 @@ +#ifndef IMS_IMU_LSM6DSL_H +#define IMS_IMU_LSM6DSL_H + +#include "imsensors/common/sensors_common.h" + +typedef struct { + ims_i2c_xfer_t i2c_xfer; + ims_delay_t delay; +} ims_lsm6dsl_cb_t; + +typedef struct { + void *pdev; + ims_lsm6dsl_cb_t cb; +} ims_lsm6dsl_t; + +ims_ret_t ims_lsm6dsl_init(ims_lsm6dsl_t *imu); +ims_ret_t ims_lsm6dsl_read_temperature(ims_lsm6dsl_t *imu, int16_t *temp); + +#endif // IMS_IMU_LSM6DSL_H diff --git a/src/imu/imu_lsm6dsl.c b/src/imu/imu_lsm6dsl.c new file mode 100644 index 0000000..39a225a --- /dev/null +++ b/src/imu/imu_lsm6dsl.c @@ -0,0 +1,98 @@ +#include "imu_lsm6dsl.h" + +#define LSM6DSL_REG_WHOAMI 0x0FU +#define LSM6DSL_REG_CTRL1_XL 0x10U +#define LSM6DSL_REG_OUT_TEMP_L 0x20U +#define LSM6DSL_REG_OUT_TEMP_H 0x21U + +#define LSM6DSL_CONST_WHOAMI 0x6AU + +#define LSM6DSL_MAXIMUM_MULTI_WRITE_SIZE 32 + +static ims_ret_t ims_lsm6dsl_whoami(ims_lsm6dsl_t *imu, uint8_t *whoami); + +static ims_ret_t ims_lsm6dsl_read_register(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t *data); +static ims_ret_t ims_lsm6dsl_read_registers(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t *data, uint16_t len); +static ims_ret_t ims_lsm6dsl_write_register(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t data); +static ims_ret_t ims_lsm6dsl_write_registers(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t *data, uint16_t len); + +ims_ret_t ims_lsm6dsl_init(ims_lsm6dsl_t *imu) { + ims_ret_t ret; + + uint8_t who_am_i; + + ret = ims_lsm6dsl_whoami(imu, &who_am_i); + if (ret != IMS_SUCCESS) { + return ret; + } + + if (who_am_i != LSM6DSL_CONST_WHOAMI) { + return IMS_FAIL; + } + + ret = ims_lsm6dsl_write_register(imu, LSM6DSL_REG_CTRL1_XL, 0xB0); + if (ret != IMS_SUCCESS) { + return IMS_FAIL; + } + + return IMS_SUCCESS; +} + +ims_ret_t ims_lsm6dsl_read_temperature(ims_lsm6dsl_t *imu, int16_t *temp) { + ims_ret_t ret; + + uint8_t rx_temp[2]; + + ret = ims_lsm6dsl_read_registers(imu, LSM6DSL_REG_OUT_TEMP_L, rx_temp, 2); + if (ret != IMS_SUCCESS) { + return ret; + } + + *temp = (int16_t)(uint16_t)((rx_temp[1] << 8U) | rx_temp[0]); + + return IMS_SUCCESS; +} + +static ims_ret_t ims_lsm6dsl_whoami(ims_lsm6dsl_t *imu, uint8_t *whoami) { + return ims_lsm6dsl_read_register(imu, LSM6DSL_REG_WHOAMI, whoami); +} + +static ims_ret_t ims_lsm6dsl_read_register(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t *data) { + return ims_lsm6dsl_read_registers(imu, addr, data, 1U); +} + +static ims_ret_t ims_lsm6dsl_read_registers(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t *data, uint16_t len) { + ims_i2c_xfer_desc_t xfer = { + .tx_size = 1U, + .tx_data = &addr, + .rx_size = len, + .rx_data = data, + }; + + return imu->cb.i2c_xfer(imu->pdev, &xfer); +} + +static ims_ret_t ims_lsm6dsl_write_register(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t data) { + return ims_lsm6dsl_write_registers(imu, addr, &data, 1U); +} + +static ims_ret_t ims_lsm6dsl_write_registers(ims_lsm6dsl_t *imu, uint8_t addr, uint8_t *data, uint16_t len) { + if (len > LSM6DSL_MAXIMUM_MULTI_WRITE_SIZE) { + return IMS_FAIL; + } + + uint8_t tx_buf[LSM6DSL_MAXIMUM_MULTI_WRITE_SIZE + 1]; + + tx_buf[0] = addr; + + memcpy(&tx_buf[1], data, len); + + ims_i2c_xfer_desc_t xfer = { + .tx_size = len + 1, + .tx_data = tx_buf, + .rx_size = 0U, + .rx_data = NULL, + }; + + return imu->cb.i2c_xfer(imu->pdev, &xfer); +} \ No newline at end of file