Skip to content

Instantly share code, notes, and snippets.

@asherkin
Last active October 19, 2016 15:32
Show Gist options
  • Save asherkin/b9caccfc45201479a3cc225cf0375903 to your computer and use it in GitHub Desktop.
Save asherkin/b9caccfc45201479a3cc225cf0375903 to your computer and use it in GitHub Desktop.
C.H.I.P. Battery Page
<?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