#!/usr/bin/perl # # v1.2 (c) 2009 2011-10-20 DocScrutinizer # # this script decodes the smartbattery BQ27000 Coulomb-Counter # v1.2 tries to deal with sysfs path changes on OM kernels, and supports N900 directly # perl-rewrite (c) 2013-01-01 jon_y # http://mg.pov.lt/maemo-ssu-irclog/%23maemo-ssu.2013-01-02.log.html#t2013-01-02T00:16:18 # # needs i2cdump executable in $PATH, so probably you need root permissions to run use strict; use warnings; my @dmp; sub pv { # print value, in: byte(s)-hex NN [NN], out: dezimal 5 digits unsigned 0..65535 my $i = 0; foreach(@_) { $i = ($i << 8) + hex($dmp[$_]); } return $i } sub printdetail { printf " RAM Registers\n"; printf " 0x00: 0x%02x CTRL Device Control Register R/W\n", pv(0x0); printf " 0x01: 0x%02x MODE Device Mode Register R/W\n", pv(0x1); printf "0x03 - 0x02: %5d AR At-Rate High - Low Byte (user writes here) 3.57 µV (1) R/W\n", pv(0x3,0x2); printf "0x05 - 0x04: %5d ARTTE At-Rate Time-to-Empty High - Low Byte Minutes R\n", pv(0x5,0x4); printf "0x07 - 0x06: %5d TEMP Reported Temperature High - Low Byte 0.25 °K R\n", pv(0x07,0x06); my $milliC = pv(0x07, 0x06) * 250 - 273150; my $C = $milliC / 1000; my $Cdecimals = $milliC - ( $C * 1000 ); my $F = ( $milliC * 18 + 320000 ) / 10000; my $at_0A = pv(0xA); printf " /4 - 273.15 = %.3f°C, %.3f°F\n", $C,$F; printf "0x09 - 0x08: %-5d VOLT Reported Voltage High - Low Byte mV R\n", pv(0x09,0x08); printf " 0x0A: 0x%x FLAGS Status Flags R\n", $at_0A; printf " %d CHGS Charge State flag. A 1 in the CHGS indicates a charge current (VSRP > VSRN). Charging.\n", !!($at_0A & 0b10000000); printf " %d NOACT No Activity flag. A 1 indicates that the voltage across RS is ~0. Neither charge nor discharge.\n", !!($at_0A & 0b01000000); printf " %d IMIN Li-ion taper current detection flag. A 1 indicates that the charge ... is considered finished.\n", !!($at_0A & 0b00100000); printf " %d CI Capacity Inaccurate flag. A 1 indicates no valid learning cycle.\n", !!($at_0A & 0b00010000); printf " %d CALIP Offset Calibration-In-Progress flag.\n", !!($at_0A & 0b000001000); printf " %d VDQ Valid Discharge flag. Learning cycle in progress.\n", !!($at_0A & 00000100); printf " %d EDV1 First End-of-Discharge-Voltage flag. A 1 indicates that voltage < EDV1\n", !!($at_0A & 0b00000010); printf " %d EDVF Final End-of-Discharge-Voltage flag. A 1 indicates that the battery has discharged to the empty capacity threshold.\n", !!($at_0A & 0b00000001); printf " 0x0B: %5d RSOC Relative State-of-Charge %% R\n", pv(0x0B); printf "0x0D - 0x0C: %5d NAC Nominal Available Capacity High - Low Byte 3.57 µVh (1) R\n", pv(0x0D,0x0C); printf " *3.57 / 20 = %5d mAh\n", pv(0x0D,0x0C) * 179 / 1000; printf "0x0F - 0x0E: %5d CACD Discharge Compensated NAC High - Low Byte 3.57 µVh (1) R\n", pv(0x0F,0x0E); printf " *3.57 / 20 = %5d mAh\n", pv(0x0F,0x0E) * 179 / 1000; printf "0x11 - 0x10: %5d CACT Temperature Compensated CACD High - Low Byte 3.57 µVh (1) R\n", pv(0x11,0x10); printf " *3.57 / 20 = %5d mAh\n", pv(0x11,0x10) * 179 / 1000; printf "0x13 - 0x12: %5d LMD Last Measured Discharge High - Low Byte 3.57 µVh (1) R\n", pv(0x13,0x12); printf " *3.57 / 20 = %5d mAh\n", pv(0x13,0x12) * 179 / 1000; printf "0x15 - 0x14: %5d AI Average Current High - Low Byte 3.57 µV (1) R\n", pv(0x15,0x14); printf " *3.57 / 20 = %5d mA\n", pv(0x15,0x14) * 179 / 1000; printf "0x17 - 0x16: %5d TTE Time-to-Empty High - Low Byte Minutes R\n", pv(0x17,0x16); printf "0x19 - 0x18: %5d TTF Time-to-Full High - Low Byte Minutes R\n", pv(0x19,0x18); printf "0x1B - 0x1A: %5d SI Standby Current High - Low Byte 3.57 µV (1) R\n", pv(0x1B,0x1A); printf " *3.57 / 20 = %5d mA\n", pv(0x1B,0x1A) * 179 / 1000; printf "0x1D - 0x1C: %5d STTE Standby Time-to-Empty High - Low Byte Minutes R\n", pv(0x1D,0x1C); printf "0x1F - 0x1E: %5d MLI Max Load Current High - Low Byte 3.57 µV (1) R\n", pv(0x1F,0x1E); printf " *3.57 / 20 = %5d mA\n", pv(0x1F,0x1E) * 179 / 1000; printf "0x21 - 0x20: %5d MLTTE Max Load Time-to-Empty High - Low Byte Minutes R\n", pv(0x21,0x20); printf "0x23 - 0x22: %5d SAE Available Energy High - Low Byte 29.2 µV2h (2) R\n", pv(0x23,0x22); printf " *29.2 / 20 = %5d mWh\n", pv(0x23,0x22) * 146 / 100; printf "0x25 - 0x24: %5d AP Average Power High - Low Byte 29.2 µV2 (2) R\n", pv(0x25,0x24); printf " *29.2 / 20 = %5d mW\n", pv(0x25,0x24) * 146 / 100; printf "0x27 - 0x26: %5d TTECP Time-to-Empty At Constant Power High-Low Byte Minutes R\n", pv(0x27,0x26); printf "0x29 - 0x28: %5d CYCL Cycle Count Since Learning Cycle High-Low Byte Cycles R\n", pv(0x29,0x28); printf "0x2B - 0x2A: %5d CYCT Cycle Count Total High - Low Byte Cycles R\n", pv(0x2B,0x2A); printf " 0x2C: %5d CSOC Compensated State-of-Charge %% R\n", pv(0x2C); print "\n"; } sub printstatic { printf "EEPROM Registers\n"; printf "0x2D - 0x6D - RESERVED R\n"; printf " 0x6E: %5d EE_EN EEPROM Program Enable R/W\n", pv(0x6E); printf "0x6F - 0x75 - RESERVED R\n"; printf " 0x76: %5d ILMD Initial Last Measured Discharge High Byte 914 µVh (1) R/W\n", pv(0x76); printf " *0x100 * 3.57 / 20 = %5d mAh fabcoded cell capacity\n", pv(0x76,0x00) * 179 / 1000; printf " 0x77: %5d SEDVF Scaled EDVF Threshold R/W\n", pv(0x77); printf " +0x100)*8 = %5d mV (@ 0%%)\n", (pv(0x77) + 0x100) * 8; printf " 0x78: %5d SEDV1 Scaled EDV1 Threshold R/W\n", pv(0x78); printf " +0x100)*8 = %5d mV (@ 6.25%%)\n", (pv(0x78) + 0x100) * 8; printf " 0x79: %5d ISLC Initial Standby Load Current 7.14 µV (1) R/W\n", pv(0x79); printf " *7.14 / 20 = %5d mA\n", pv(0x79) * 714 / 2000; printf " 0x7A: %5d DMFSD Digital Magnitude Filter and Self-Discharge Rate Constants R/W\n", pv(0x7A); printf " 0x7B: %5d TAPER Aging Estimate Enable, Charge Termin. Taper I 228 µV (1) R/W\n", pv(0x7B); printf " 0x7C: %5d PKCFG Pack Configuration Values R/W\n", pv(0x7C); printf " 0x7D: %5d IMLC Initial Max Load Current, OR, ID#3 457 µV (1) R/W\n", pv(0x7D); printf " 0x7E: %5d DCOMP Discharge Rate Compensation Constants, OR, ID#2 R/W\n", pv(0x7E); printf " 0x7F: %5d TCOMP Temperature Compensation Constants, OR, ID#1 R/W\n", pv(0x7F); printf "\n"; printf "(1) Divide by Rs in milliohms to convert µV to mA or µVh to mAh.\n"; printf "(2) Divide by Rs in milliohms to convert µV2 to mW or µV2h to mWh.\n"; printf "Rs=20mOhm\n"; } #main my $dmppath = `find /sys/devices/ -path '*/hdq/*' -name dump 2>/dev/null`; my $dmpcmd; if ($dmppath){ $dmpcmd = qq{cat ${1:-$dmppath}| tr -s '\n ' ' '}; } else { $dmpcmd = q{i2cdump -y 2 0x55 b|tail -n +2|cut -d ' ' -f 2-17}; } #dmp=(`cat ${1:-/sys/devices/platform/s3c24xx_pwm.0/hdq.0/hdq/dump}| tr -s '\n ' ' '`) @dmp = split(/[\s|\n]/,`$dmpcmd`); if(scalar(@dmp) == 0){ exit 1; # read failure } printdetail(); printstatic();