Last active
October 19, 2016 15:32
-
-
Save asherkin/b9caccfc45201479a3cc225cf0375903 to your computer and use it in GitHub Desktop.
C.H.I.P. Battery Page
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Register { | |
// Single-register bitflags | |
const POWER_INPUT_STATUS = 0x00; | |
const POWER_OPERATING_MODE_AND_CHARGE_STATUS = 0x01; | |
const ADC_ENABLE_ONE = 0x82; | |
const ADC_ENABLE_TWO = 0x83; | |
// Double-register values | |
const ACIN_VOLTAGE = 0x56; | |
const ACIN_CURRENT = 0x58; | |
const VBUS_VOLTAGE = 0x5A; | |
const VBUS_CURRENT = 0x5C; | |
const INTERNAL_TEMPERATURE = 0x5E; | |
const TEMPERATURE_SENSOR_VOLTAGE = 0x62; | |
const BATTERY_VOLTAGE = 0x78; | |
const BATTERY_CHARGE_CURRENT = 0x7A; | |
const BATTERY_DISCHARGE_CURRENT = 0x7C; | |
const APS_VOLTAGE = 0x7E; | |
// Other | |
const FUEL_GAUGE = 0xB9; | |
public static function Get($register) { | |
$register = dechex($register); | |
$command = '/usr/sbin/i2cget -y -f 0 0x34 0x'.$register.' b'; | |
$result = exec($command); | |
$result = intval($result, 0); | |
return $result; | |
} | |
public static function Measurement($register, $overbits = 4) { | |
$register = dechex($register); | |
$command = '/usr/sbin/i2cget -y -f 0 0x34 0x'.$register.' w'; | |
$result = exec($command); | |
$result = intval($result, 0); | |
$low = ($result >> 8) & (PHP_INT_MAX >> 7); | |
$high = $result & 0xFF; | |
$result = ($high << $overbits) | $low; | |
return $result; | |
} | |
} | |
class PowerInputStatus { | |
const START_SOURCE = (1 << 0); | |
const INPUT_SHORTED = (1 << 1); | |
const BATTERY_CURRENT_DIRECTION = (1 << 2); | |
const VBUS_GREATER_THAN_VHOLD = (1 << 3); | |
const VBUS_AVAILABLE = (1 << 4); | |
const VBUS_PRESENT = (1 << 5); | |
const ACIN_AVAILABLE = (1 << 6); | |
const ACIN_PRESENT = (1 << 7); | |
public static function Describe($value) { | |
$output = []; | |
if (($value & self::START_SOURCE) !== 0) | |
$output[] = 'START_SOURCE'; | |
if (($value & self::INPUT_SHORTED) !== 0) | |
$output[] = 'INPUT_SHORTED'; | |
if (($value & self::BATTERY_CURRENT_DIRECTION) !== 0) | |
$output[] = 'BATTERY_CURRENT_DIRECTION'; | |
if (($value & self::VBUS_GREATER_THAN_VHOLD) !== 0) | |
$output[] = 'VBUS_GREATER_THAN_VHOLD'; | |
if (($value & self::VBUS_AVAILABLE) !== 0) | |
$output[] = 'VBUS_AVAILABLE'; | |
if (($value & self::VBUS_PRESENT) !== 0) | |
$output[] = 'VBUS_PRESENT'; | |
if (($value & self::ACIN_AVAILABLE) !== 0) | |
$output[] = 'ACIN_AVAILABLE'; | |
if (($value & self::ACIN_PRESENT) !== 0) | |
$output[] = 'ACIN_PRESENT'; | |
if (empty($output)) | |
return '0'; | |
return implode(' | ', $output); | |
} | |
} | |
class PowerOperatingModeAndChargeStatus { | |
const RESERVED_ZERO = (1 << 0); | |
const RESERVED_ONE = (1 << 1); | |
const CHARGE_UNDER_CURRENT = (1 << 2); | |
const BATTERY_ACTIVE = (1 << 3); | |
const RESERVED_FOUR = (1 << 4); | |
const BATTERY_PRESENT = (1 << 5); | |
const BATTERY_CHARGING = (1 << 6); | |
const OVER_TEMPERATURE = (1 << 7); | |
public static function Describe($value) { | |
$output = []; | |
if (($value & self::RESERVED_ZERO) !== 0) | |
$output[] = 'RESERVED_ZERO'; | |
if (($value & self::RESERVED_ONE) !== 0) | |
$output[] = 'RESERVED_ONE'; | |
if (($value & self::CHARGE_UNDER_CURRENT) !== 0) | |
$output[] = 'CHARGE_UNDER_CURRENT'; | |
if (($value & self::BATTERY_ACTIVE) !== 0) | |
$output[] = 'BATTERY_ACTIVE'; | |
if (($value & self::RESERVED_FOUR) !== 0) | |
$output[] = 'RESERVED_FOUR'; | |
if (($value & self::BATTERY_PRESENT) !== 0) | |
$output[] = 'BATTERY_PRESENT'; | |
if (($value & self::BATTERY_CHARGING) !== 0) | |
$output[] = 'BATTERY_CHARGING'; | |
if (($value & self::OVER_TEMPERATURE) !== 0) | |
$output[] = 'OVER_TEMPERATURE'; | |
if (empty($output)) | |
return '0'; | |
return implode(' | ', $output); | |
} | |
} | |
class ADCEnableOne { | |
const TS = (1 << 0); | |
const APS_VOLTAGE = (1 << 1); | |
const VBUS_CURRENT = (1 << 2); | |
const VBUS_VOLTAGE = (1 << 3); | |
const ACIN_CURRENT = (1 << 4); | |
const ACIN_VOLTAGE = (1 << 5); | |
const BATTERY_CURRENT = (1 << 6); | |
const BATTERY_VOLTAGE = (1 << 7); | |
public static function Describe($value) { | |
$output = []; | |
if (($value & self::TS) !== 0) | |
$output[] = 'TS'; | |
if (($value & self::APS_VOLTAGE) !== 0) | |
$output[] = 'APS_VOLTAGE'; | |
if (($value & self::VBUS_CURRENT) !== 0) | |
$output[] = 'VBUS_CURRENT'; | |
if (($value & self::VBUS_VOLTAGE) !== 0) | |
$output[] = 'VBUS_VOLTAGE'; | |
if (($value & self::ACIN_CURRENT) !== 0) | |
$output[] = 'ACIN_CURRENT'; | |
if (($value & self::ACIN_VOLTAGE) !== 0) | |
$output[] = 'ACIN_VOLTAGE'; | |
if (($value & self::BATTERY_CURRENT) !== 0) | |
$output[] = 'BATTERY_CURRENT'; | |
if (($value & self::BATTERY_VOLTAGE) !== 0) | |
$output[] = 'BATTERY_VOLTAGE'; | |
if (empty($output)) | |
return '0'; | |
return implode(' | ', $output); | |
} | |
} | |
class ADCEnableTwo { | |
const RESERVED_ZERO = (1 << 0); | |
const RESERVED_ONE = (1 << 1); | |
const GPIO_ONE = (1 << 2); | |
const GPIO_TWO = (1 << 3); | |
const RESERVED_FOUR = (1 << 4); | |
const RESERVED_FIVE = (1 << 5); | |
const RESERVED_SIX = (1 << 6); | |
const INTERNAL_TEMPERATURE = (1 << 7); | |
public static function Describe($value) { | |
$output = []; | |
if (($value & self::RESERVED_ZERO) !== 0) | |
$output[] = 'RESERVED_ZERO'; | |
if (($value & self::RESERVED_ONE) !== 0) | |
$output[] = 'RESERVED_ONE'; | |
if (($value & self::GPIO_ONE) !== 0) | |
$output[] = 'GPIO_ONE'; | |
if (($value & self::GPIO_TWO) !== 0) | |
$output[] = 'GPIO_TWO'; | |
if (($value & self::RESERVED_FOUR) !== 0) | |
$output[] = 'RESERVED_FOUR'; | |
if (($value & self::RESERVED_FIVE) !== 0) | |
$output[] = 'RESERVED_FIVE'; | |
if (($value & self::RESERVED_SIX) !== 0) | |
$output[] = 'RESERVED_SIX'; | |
if (($value & self::INTERNAL_TEMPERATURE) !== 0) | |
$output[] = 'INTERNAL_TEMPERATURE'; | |
if (empty($output)) | |
return '0'; | |
return implode(' | ', $output); | |
} | |
} | |
if (isset($_GET['json'])) { | |
$output = []; | |
$output['is_charging'] = (Register::Get(Register::POWER_OPERATING_MODE_AND_CHARGE_STATUS) & PowerOperatingModeAndChargeStatus::BATTERY_CHARGING) != 0; | |
$output['vbus_voltage'] = (Register::Measurement(Register::VBUS_VOLTAGE) * 1.7) * 0.001; | |
$output['vbus_current'] = (Register::Measurement(Register::VBUS_CURRENT) * 0.375) * 0.001; | |
$output['battery_charge_current'] = (Register::Measurement(Register::BATTERY_CHARGE_CURRENT) * 0.5) * 0.001; | |
$output['battery_discharge_current'] = (Register::Measurement(Register::BATTERY_DISCHARGE_CURRENT, 5) * 0.5) * 0.001; | |
$output['fuel_gauge'] = Register::Get(Register::FUEL_GAUGE) & ~(1 << 7); | |
echo json_encode($output); | |
exit(); | |
} | |
echo '<pre style="color: darkgrey; font-size: 10px;">'; | |
$power_operating_mode_and_charge_status = Register::Get(Register::POWER_OPERATING_MODE_AND_CHARGE_STATUS); | |
$is_charging = ($power_operating_mode_and_charge_status & PowerOperatingModeAndChargeStatus::BATTERY_CHARGING) != 0; | |
$has_battery = ($power_operating_mode_and_charge_status & PowerOperatingModeAndChargeStatus::BATTERY_PRESENT) != 0; | |
echo 'POWER_INPUT_STATUS: '.PowerInputStatus::Describe(Register::Get(Register::POWER_INPUT_STATUS)).PHP_EOL; | |
echo 'POWER_OPERATING_MODE_AND_CHARGE_STATUS: '.PowerOperatingModeAndChargeStatus::Describe($power_operating_mode_and_charge_status).PHP_EOL; | |
echo PHP_EOL; | |
echo 'ADC_ENABLE_ONE: '.ADCEnableOne::Describe(Register::Get(Register::ADC_ENABLE_ONE)).PHP_EOL; | |
echo 'ADC_ENABLE_TWO: '.ADCEnableTwo::Describe(Register::Get(Register::ADC_ENABLE_TWO)).PHP_EOL; | |
echo PHP_EOL; | |
echo 'ACIN_VOLTAGE: '.(Register::Measurement(Register::ACIN_VOLTAGE) * 1.7).' mV'.PHP_EOL; | |
echo 'ACIN_CURRENT: '.(Register::Measurement(Register::ACIN_CURRENT) * 0.625).' mA'.PHP_EOL; | |
echo 'VBUS_VOLTAGE: '.(Register::Measurement(Register::VBUS_VOLTAGE) * 1.7).' mV'.PHP_EOL; | |
echo 'VBUS_CURRENT: '.(Register::Measurement(Register::VBUS_CURRENT) * 0.375).' mA'.PHP_EOL; | |
echo 'INTERNAL_TEMPERATURE: '.(-144.7 + (Register::Measurement(Register::INTERNAL_TEMPERATURE) * 0.1)).' C'.PHP_EOL; | |
echo 'TEMPERATURE_SENSOR_VOLTAGE: '.(Register::Measurement(Register::TEMPERATURE_SENSOR_VOLTAGE) * 0.8).' mV'.PHP_EOL; | |
echo 'APS_VOLTAGE: '.(Register::Measurement(Register::APS_VOLTAGE) * 1.4).' mV'.PHP_EOL; | |
echo 'BATTERY_VOLTAGE: '.(Register::Measurement(Register::BATTERY_VOLTAGE) * 1.1).' mV'.PHP_EOL; | |
echo 'BATTERY_CHARGE_CURRENT: '.(Register::Measurement(Register::BATTERY_CHARGE_CURRENT) * 0.5).' mA'.PHP_EOL; | |
echo 'BATTERY_DISCHARGE_CURRENT: '.(Register::Measurement(Register::BATTERY_DISCHARGE_CURRENT, 5) * 0.5).' mA'.PHP_EOL; | |
echo PHP_EOL; | |
$fuel_gauge = Register::Get(Register::FUEL_GAUGE) & ~(1 << 7); | |
echo 'FUEL_GAUGE: '.$fuel_gauge.'%'.PHP_EOL; | |
$fuel_color = 'lawngreen'; | |
if ($fuel_gauge < 25) | |
$fuel_color = 'gold'; | |
if ($fuel_gauge < 10) | |
$fuel_color = 'crimson'; | |
echo '</pre>'; | |
?> | |
<div style="position: fixed; width: 100px; height: 20px; top: 50%; left: 50%; margin-top: -160px; margin-left: -50px; background-color: black; border-top-left-radius: 5px; border-top-right-radius: 5px;"></div> | |
<div style="position: fixed; width: 170px; height: 270px; top: 50%; left: 50%; margin-top: -140px; margin-left: -100px; background-color: white; border: 15px solid black; border-radius: 10px;"> | |
<div style="position: absolute; left: 0; right: 0; bottom: 0; border: 3px solid white; box-sizing: border-box; background-color: <?php echo $fuel_color; ?>; height: <?php echo $fuel_gauge; ?>%;"></div> | |
</div> | |
<?php if (!$has_battery) { ?> | |
<div style="position: fixed; width: 20px; height: 350px; top: 50%; left: 50%; margin-top: -175px; margin-left: -10px; background-color: crimson; transform: rotate(-45deg);"></div> | |
<?php } ?> | |
<?php if ($is_charging) { ?> | |
<div style="position: fixed; width: 80px; height: 30px; top: 50%; left: 50%; margin-top: -8px; margin-left: -40px; background-color: black; border-bottom-left-radius: 30px; border-bottom-right-radius: 30px;"></div> | |
<div style="position: fixed; width: 15px; height: 25px; top: 50%; left: 50%; margin-top: -35px; margin-left: -25px; background-color: black;"></div> | |
<div style="position: fixed; width: 15px; height: 25px; top: 50%; left: 50%; margin-top: -35px; margin-left: 10px; background-color: black;"></div> | |
<div style="position: fixed; width: 20px; height: 35px; top: 50%; left: 50%; margin-top: 24px; margin-left: -10px; background-color: black;"></div> | |
<?php } ?> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment