batt_smbus: Adds functions for reading out the SBS Info

Functions added for reading out the following info:
 - Manufacturer Name
 - Device Name
 - Serial Number
 - Device Chemistry
This commit is contained in:
ksschwabe
2016-02-18 21:47:09 +01:00
committed by Lorenz Meier
parent e3f2467b91
commit 27a645353b
+272 -22
View File
@@ -88,8 +88,11 @@
#define BATT_SMBUS_FULL_CHARGE_CAPACITY 0x10 ///< capacity when fully charged
#define BATT_SMBUS_DESIGN_CAPACITY 0x18 ///< design capacity register
#define BATT_SMBUS_DESIGN_VOLTAGE 0x19 ///< design voltage register
#define BATT_SMBUS_SERIALNUM 0x1c ///< serial number register
#define BATT_SMBUS_MANUFACTURE_NAME 0x20 ///< manufacturer name
#define BATT_SMBUS_MANUFACTURE_DATE 0x1B ///< manufacture date register
#define BATT_SMBUS_SERIAL_NUMBER 0x1C ///< serial number register
#define BATT_SMBUS_MANUFACTURER_NAME 0x20 ///< manufacturer name
#define BATT_SMBUS_DEVICE_NAME 0x21 ///< device name register
#define BATT_SMBUS_DEVICE_CHEMISTRY 0x22 ///< device chemistry register
#define BATT_SMBUS_MANUFACTURER_DATA 0x23 ///< manufacturer data
#define BATT_SMBUS_MANUFACTURE_INFO 0x25 ///< cell voltage register
#define BATT_SMBUS_CURRENT 0x2a ///< current register
@@ -139,6 +142,57 @@ public:
*/
int search();
/**
* Get the SBS manufacturer name of the battery device
*
* @param manufacturer_name pointer a buffer into which the manufacturer name is to be written
* @param max_length the maximum number of bytes to attempt to read from the manufacturer name register, including the null character that is appended to the end
*
* @return the number of bytes read
*/
uint8_t manufacturer_name(uint8_t *man_name, uint8_t max_length);
/**
* Return the SBS manufacture date of the battery device
*
* @return the date in the following format:
* see Smart Battery Data Specification, Revision 1.1
* http://sbs-forum.org/specs/sbdat110.pdf for more details
* Date as uint16_t = (year-1980) * 512 + month * 32 + day
* | Field | Bits | Format | Allowable Values |
* | ----- | ---- | ------------------ | ------------------------------------------ |
* | Day 0-4 5-bit binary value 1-31 (corresponds to day) |
* | Month 5-8 4-bit binary value 1-12 (corresponds to month number) |
* | Year 9-15 7-bit binary value 0-127 (corresponds to year biased by 1980) |
* otherwise, return 0 on failure
*/
uint16_t manufacture_date();
/**
* Get the SBS device name of the battery device
*
* @param dev_name pointer a buffer into which the device name is to be written
* @param max_length the maximum number of bytes to attempt to read from the device name register, including the null character that is appended to the end
*
* @return the number of bytes read
*/
uint8_t device_name(uint8_t *dev_name, uint8_t max_length);
/**
* Return the SBS serial number of the battery device
*/
uint16_t serial_number();
/**
* Get the SBS device chemistry of the battery device
*
* @param dev_chem pointer a buffer into which the device chemistry is to be written
* @param max_length the maximum number of bytes to attempt to read from the device chemistry register, including the null character that is appended to the end
*
* @return the number of bytes read
*/
uint8_t device_chemistry(uint8_t *dev_chem, uint8_t max_length);
protected:
/**
* Check if the device can be contacted
@@ -222,6 +276,12 @@ void batt_smbus_usage();
extern "C" __EXPORT int batt_smbus_main(int argc, char *argv[]);
int manufacturer_name();
int manufacture_date();
int device_name();
int serial_number();
int device_chemistry();
BATT_SMBUS::BATT_SMBUS(int bus, uint16_t batt_smbus_addr) :
I2C("batt_smbus", BATT_SMBUS0_DEVICE_PATH, bus, batt_smbus_addr, 100000),
_enabled(false),
@@ -368,6 +428,82 @@ BATT_SMBUS::search()
return OK;
}
uint8_t
BATT_SMBUS::manufacturer_name(uint8_t *man_name, uint8_t max_length)
{
uint8_t len = read_block(BATT_SMBUS_MANUFACTURER_NAME, man_name, max_length, false);
if (len > 0) {
if (len >= max_length - 1) {
man_name[max_length - 1] = 0;
} else {
man_name[len] = 0;
}
}
return len;
}
uint16_t
BATT_SMBUS::manufacture_date()
{
uint16_t man_date;
if (read_reg(BATT_SMBUS_MANUFACTURE_DATE, man_date) == OK) {
return man_date;
}
// Return 0 if could not read the date correctly
return 0;
}
uint8_t
BATT_SMBUS::device_name(uint8_t *dev_name, uint8_t max_length)
{
uint8_t len = read_block(BATT_SMBUS_DEVICE_NAME, dev_name, max_length, false);
if (len > 0) {
if (len >= max_length - 1) {
dev_name[max_length - 1] = 0;
} else {
dev_name[len] = 0;
}
}
return len;
}
uint16_t
BATT_SMBUS::serial_number()
{
uint16_t serial_num;
if (read_reg(BATT_SMBUS_SERIAL_NUMBER, serial_num) == OK) {
return serial_num;
}
return -1;
}
uint8_t
BATT_SMBUS::device_chemistry(uint8_t *dev_chem, uint8_t max_length)
{
uint8_t len = read_block(BATT_SMBUS_DEVICE_CHEMISTRY, dev_chem, max_length, false);
if (len > 0) {
if (len >= max_length - 1) {
dev_chem[max_length - 1] = 0;
} else {
dev_chem[len] = 0;
}
}
return len;
}
int
BATT_SMBUS::probe()
{
@@ -451,28 +587,28 @@ BATT_SMBUS::cycle()
}
}
/*
// read the button press indicator
if (read_block(BATT_SMBUS_MANUFACTURER_DATA, buff, 6, false) == 6) {
bool pressed = (buff[1] >> 3) & 0x01;
/*
// read the button press indicator
if (read_block(BATT_SMBUS_MANUFACTURER_DATA, buff, 6, false) == 6) {
bool pressed = (buff[1] >> 3) & 0x01;
if(_button_press_counts >= ((BATT_SMBUS_BUTTON_DEBOUNCE_MS * 1000) / BATT_SMBUS_MEASUREMENT_INTERVAL_US)) {
// battery will power off
new_report.is_powering_off = true;
// warn only once
if(_button_press_counts++ == ((BATT_SMBUS_BUTTON_DEBOUNCE_MS * 1000) / BATT_SMBUS_MEASUREMENT_INTERVAL_US)) {
warnx("system is shutting down NOW...");
if(_button_press_counts >= ((BATT_SMBUS_BUTTON_DEBOUNCE_MS * 1000) / BATT_SMBUS_MEASUREMENT_INTERVAL_US)) {
// battery will power off
new_report.is_powering_off = true;
// warn only once
if(_button_press_counts++ == ((BATT_SMBUS_BUTTON_DEBOUNCE_MS * 1000) / BATT_SMBUS_MEASUREMENT_INTERVAL_US)) {
warnx("system is shutting down NOW...");
}
} else if(pressed) {
// battery will power off if the button is held
_button_press_counts++;
} else {
// button released early, reset counters
_button_press_counts = 0;
new_report.is_powering_off = false;
}
} else if(pressed) {
// battery will power off if the button is held
_button_press_counts++;
} else {
// button released early, reset counters
_button_press_counts = 0;
new_report.is_powering_off = false;
}
}
*/
*/
// publish to orb
if (_batt_topic != -1) {
@@ -693,12 +829,92 @@ BATT_SMBUS::ManufacturerAccess(uint16_t cmd)
void
batt_smbus_usage()
{
warnx("missing command: try 'start', 'test', 'stop', 'search'");
warnx("missing command: try 'start', 'test', 'stop', 'search', 'man_name', 'man_date', 'dev_name', 'serial_num', 'dev_chem', 'sbs_info'");
warnx("options:");
warnx(" -b i2cbus (%d)", BATT_SMBUS_I2C_BUS);
warnx(" -a addr (0x%x)", BATT_SMBUS_ADDR);
}
int
manufacturer_name()
{
uint8_t man_name[21];
uint8_t len = g_batt_smbus->manufacturer_name(man_name, sizeof(man_name));
if (len > 0) {
warnx("The manufacturer name: %s", man_name);
return OK;
} else {
warnx("Unable to read manufacturer name.");
}
return -1;
}
int
manufacture_date()
{
uint16_t man_date = g_batt_smbus->manufacture_date();
if (man_date > 0) {
// Convert the uint16_t into human-readable date format
uint16_t year = ((man_date >> 9) & 0xFF) + 1980;
uint8_t month = (man_date >> 5) & 0xF;
uint8_t day = man_date & 0x1F;
warnx("The manufacturer date is: %d which is %4d-%02d-%02d", man_date, year, month, day);
return OK;
} else {
warnx("Unable to read the manufacturer date.");
}
return -1;
}
int
device_name()
{
uint8_t device_name[21];
uint8_t len = g_batt_smbus->device_name(device_name, sizeof(device_name));
if (len > 0) {
warnx("The device name: %s", device_name);
return OK;
} else {
warnx("Unable to read device name.");
}
return -1;
}
int
serial_number()
{
uint16_t serial_num = g_batt_smbus->serial_number();
warnx("The serial number: 0x%04x (%d in decimal)", serial_num, serial_num);
return OK;
}
int
device_chemistry()
{
uint8_t device_chemistry[5];
uint8_t len = g_batt_smbus->device_chemistry(device_chemistry, sizeof(device_chemistry));
if (len > 0) {
warnx("The device chemistry: %s", device_chemistry);
return OK;
} else {
warnx("Unable to read device chemistry.");
}
return -1;
}
int
batt_smbus_main(int argc, char *argv[])
{
@@ -776,6 +992,40 @@ batt_smbus_main(int argc, char *argv[])
exit(0);
}
if (!strcmp(verb, "man_name")) {
manufacturer_name();
exit(0);
}
if (!strcmp(verb, "man_date")) {
manufacture_date();
exit(0);
}
if (!strcmp(verb, "dev_name")) {
device_name();
exit(0);
}
if (!strcmp(verb, "serial_num")) {
serial_number();
exit(0);
}
if (!strcmp(verb, "dev_chem")) {
device_chemistry();
exit(0);
}
if (!strcmp(verb, "sbs_info")) {
manufacturer_name();
manufacture_date();
device_name();
serial_number();
device_chemistry();
exit(0);
}
batt_smbus_usage();
exit(0);
}