1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/drivers/lc709203f/lc709203f.c

474 lines
15 KiB
C

/*
* Copyright (C) 2017 RWTH Aachen, Steffen Robertz, Josua Arndt
*
* This file is subject to the terms and conditions of the GNU Lesser
* General Public License v2.1. See the file LICENSE in the top level
* directory for more details.
*/
/**
* @ingroup drivers_lc709203f
* @{
*
* @file
* @brief lc709203f battery fuel gauge device driver
*
* @author Steffen Robertz <steffen.robertz@rwth-aachen.de>
* @author Josua Arndt <jarndt@ias.rwth-aachen.de>
* @}
*/
#include "lc709203f.h"
#include "assert.h"
#define ENABLE_DEBUG 0
#include "debug.h"
/*
* does a crc check and returns the checksum
*/
static uint8_t _get_crc(uint8_t *rec_values, uint8_t len)
{
uint8_t crc = 0x00;
uint8_t current_byte;
uint8_t bit;
for (current_byte = 0; current_byte < len; current_byte++) {
crc ^= (rec_values[current_byte]);
for (bit = 8; bit > 0; bit--) {
if (crc & 0x80) {
crc = (crc << 1) ^ LC709203F_CRC_POLYNOMIAL;
}
else {
crc = (crc << 1);
}
}
}
return crc;
}
int lc709203f_init(lc709203f_t *dev, const lc709203f_params_t *params)
{
assert(dev && params);
dev->params = *params;
dev->bus = params->bus;
dev->addr = params->addr;
gpio_init_int(dev->params.alarm_pin, GPIO_IN, GPIO_FALLING, dev->cb, dev->arg);
return LC709203F_OK;
}
int16_t lc709203f_get_voltage(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CELL_VOLTAGE, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_voltage(): Error reading or writing\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CELL_VOLTAGE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_rsoc(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_RSOC, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_rsoc(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_RSOC, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_ite(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ITE, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_rsoc(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ITE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_id(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ID, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_id(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ID, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_cell_temp(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CELL_TEMP, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_cell_temp(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CELL_TEMP, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
/* sensor temperature is given in 0.1K -> -2731.5 would be the correct value
* returning in 0.1°C int16_t -> using rounded 2732 */
return ((((int16_t)rec_buf[1] << 8) | rec_buf[0]) - 2732);
}
lc709203f_temp_obtaining_mode_t lc709203f_get_status_bit(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_STATUS, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_status_bit(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_STATUS, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
lc709203f_power_mode_t lc709203f_get_power_mode(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_POWER_MODE, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_power_mode(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_POWER_MODE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_alarm_low_voltage(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ALARM_VOLTAGE, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_alarm_low_voltage(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ALARM_VOLTAGE, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_alarm_low_rsoc(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_ALARM_RSOC, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_alarm_low_rsoc(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_ALARM_RSOC, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_change_of_parameter(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CHANGE_PARAMETER, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_change_of_parameter(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CHANGE_PARAMETER, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_apt(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_APT, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_apt(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_APT, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_apa(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_APA, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_apa(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_APA, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
lc709203f_current_direction_t lc709203f_get_current_direction(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_CURRENT_DIRECTION, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_current_direction(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_CURRENT_DIRECTION, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
int16_t lc709203f_get_thermistor_b(const lc709203f_t *dev)
{
assert(dev);
uint8_t rec_buf[3];
i2c_acquire(dev->bus);
int8_t control = i2c_read_regs(dev->bus, dev->addr, LC709203F_REG_THERMISTOR, rec_buf, 3, 0);
i2c_release(dev->bus);
if (control != 0) {
DEBUG("get_thermistor_b(): Error reading\n");
return 0;
}
uint8_t crc_buf[5] = { dev->addr << 1, LC709203F_REG_THERMISTOR, ((dev->addr << 1) | 0x01), rec_buf[0], rec_buf[1] };
if (_get_crc(crc_buf, 5) != rec_buf[2]) {
DEBUG("CRC Error \n");
return 0;
}
return (((unsigned int)rec_buf[1] << 8) | rec_buf[0]);
}
void lc709203f_set_rsoc_before(const lc709203f_t *dev)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_BEFORE_RSOC, 0x55, 0xAA };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_thermistor_b(const lc709203f_t *dev, const unsigned int value)
{
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_THERMISTOR, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_rsoc_initial(const lc709203f_t *dev)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_INITIAL_RSOC, 0x55, 0xAA };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
int8_t lc709203f_set_cell_temp(const lc709203f_t *dev, const unsigned int value)
{
assert(dev);
if (!(value >= 0x9e4 && value <= 0xD04)) {
DEBUG("gauge_set_cell_temp(): temp outside of range \n");
return LC709203F_CELL_TEMP_INVALID;
}
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_CELL_TEMP, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
int8_t ret_val = i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
return ret_val;
}
void lc709203f_set_current_direction(const lc709203f_t *dev, const lc709203f_current_direction_t direction)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_CURRENT_DIRECTION, (uint8_t)direction, (uint8_t)direction << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_apa(const lc709203f_t *dev, const uint8_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_APA, value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_apt(const lc709203f_t *dev, const unsigned int value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_APT, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_change_of_parameter(const lc709203f_t *dev, const lc709203f_battery_profile_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_CHANGE_PARAMETER, (uint8_t) value, (uint8_t) value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_alarm_low_rsoc(const lc709203f_t *dev, const uint8_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_ALARM_RSOC, value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_alarm_low_cell_voltage(const lc709203f_t *dev, const unsigned int value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_ALARM_VOLTAGE, value, value << 8 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_power_mode(const lc709203f_t *dev, const lc709203f_power_mode_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_POWER_MODE, (uint8_t) value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}
void lc709203f_set_status_bit(const lc709203f_t *dev, const lc709203f_temp_obtaining_mode_t value)
{
assert(dev);
uint8_t crc_buf[4] = { dev->addr << 1, LC709203F_REG_STATUS, (uint8_t) value, 0 };
uint8_t send_buf[3] = { crc_buf[2], crc_buf[3], _get_crc(crc_buf, 4) };
i2c_acquire(dev->bus);
i2c_write_regs(dev->bus, dev->addr, crc_buf[1], send_buf, 3, 0);
i2c_release(dev->bus);
}