diff --git a/firmware/drivers/axp-2101.c b/firmware/drivers/axp-2101.c index b2187d3274..bf1782f6d8 100644 --- a/firmware/drivers/axp-2101.c +++ b/firmware/drivers/axp-2101.c @@ -394,13 +394,12 @@ int axp2101_supply_get_voltage(int supply) return val; } -/* TODO: can we trust the battery current direction? */ int axp2101_battery_status(void) { int r = i2c_reg_read1(AXP_PMU_BUS, AXP_PMU_ADDR, AXP2101_REG_PMU_STATUS2); - if((r >> 5) & 0x03 == 0) { + if(((r >> 5) & 0x03) == 0) { return AXP2101_BATT_FULL; - } else if((r >> 5) & 0x03 == 01) { + } else if(((r >> 5) & 0x03) == 1) { return AXP2101_BATT_CHARGING; } else { return AXP2101_BATT_DISCHARGING; diff --git a/firmware/export/axp-2101.h b/firmware/export/axp-2101.h index 228e0ae2a4..e84f552730 100644 --- a/firmware/export/axp-2101.h +++ b/firmware/export/axp-2101.h @@ -196,6 +196,8 @@ extern int axp2101_adc_conv_raw(int adc, int value); extern void axp2101_adc_set_enabled(int adc_bits); extern int axp2101_adc_get_rate(void); +extern int axp2101_egauge_read(void); + /* Set/get maximum charging current in milliamps */ extern void axp2101_set_charge_current(int current_mA); extern int axp2101_get_charge_current(void); diff --git a/firmware/export/config.h b/firmware/export/config.h index 5b84150347..7fe7299452 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -204,6 +204,9 @@ * use the charging hardware. */ /* CONFIG_BATTERY_MEASURE bits */ +/* If both VOLTAGE_MEASURE and PERCENTAGE_MEASURE are defined, + * _battery_level() (percentage) will be preferred, unless _battery_level() + * returns -1, then voltage will be used from _voltage_level(). */ #define VOLTAGE_MEASURE 1 /* Target can report battery voltage * Usually native ports */ #define PERCENTAGE_MEASURE 2 /* Target can report remaining capacity in % diff --git a/firmware/export/config/erosqnative.h b/firmware/export/config/erosqnative.h index 648c5859ab..e245d4ad4e 100644 --- a/firmware/export/config/erosqnative.h +++ b/firmware/export/config/erosqnative.h @@ -97,7 +97,7 @@ #define STORAGE_NEEDS_BOUNCE_BUFFER /* Power management */ -#define CONFIG_BATTERY_MEASURE (VOLTAGE_MEASURE/*|CURRENT_MEASURE*/) +#define CONFIG_BATTERY_MEASURE (VOLTAGE_MEASURE | PERCENTAGE_MEASURE/*|CURRENT_MEASURE*/) #define CONFIG_CHARGING CHARGING_MONITOR #define HAVE_SW_POWEROFF diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 95763dc950..ae0bd60c28 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -302,8 +302,9 @@ static void send_battery_level_event(int percent) } } -#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) && \ - (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) +#if (!(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) && \ + (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE)) || \ + (CONFIG_BATTERY_MEASURE & (PERCENTAGE_MEASURE | VOLTAGE_MEASURE)) /* Look into the percent_to_volt_* table and estimate the battery level. */ static int voltage_to_percent(int voltage, const short* table) { @@ -360,7 +361,12 @@ static int voltage_to_battery_level(int millivolts) */ static void battery_status_update(void) { -#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE +#if CONFIG_BATTERY_MEASURE & (PERCENTAGE_MEASURE | VOLTAGE_MEASURE) + int level = _battery_level(); + if (level == -1) { + level = voltage_to_battery_level(voltage_now); + } +#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE int level = _battery_level(); #elif CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE int level = voltage_to_battery_level(voltage_now); @@ -429,7 +435,12 @@ void battery_read_info(int *voltage, int *level) *voltage = millivolts; if (level) { -#if (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) +#if (CONFIG_BATTERY_MEASURE & (PERCENTAGE_MEASURE | VOLTAGE_MEASURE)) + *level = _battery_level(); + if (*level == -1) { + *level = voltage_to_battery_level(millivolts); + } +#elif (CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) *level = _battery_level(); #elif (CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) *level = voltage_to_battery_level(millivolts); @@ -477,6 +488,9 @@ bool battery_level_safe(void) { #if defined(NO_LOW_BATTERY_SHUTDOWN) return true; +#elif CONFIG_BATTERY_MEASURE & (PERCENTAGE_MEASURE | VOLTAGE_MEASURE) + /* if we have both, prefer voltage? */ + return voltage_now > battery_level_dangerous[battery_type]; #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE return percent_now > 0; #elif defined(HAVE_BATTERY_SWITCH) @@ -508,6 +522,8 @@ bool query_force_shutdown(void) #if defined(NO_LOW_BATTERY_SHUTDOWN) return false; +#elif CONFIG_BATTERY_MEASURE & (PERCENTAGE_MEASURE | VOLTAGE_MEASURE) + return voltage_now < battery_level_shutoff[battery_type]; #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE return percent_now == 0; #elif defined(HAVE_BATTERY_SWITCH) diff --git a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c index 0f9eb3fcd0..8d55c06c4f 100644 --- a/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c +++ b/firmware/target/mips/ingenic_x1000/erosqnative/power-erosqnative.c @@ -212,6 +212,21 @@ bool charging_state(void) } } +int _battery_level(void) +{ + int devicever; +#if defined(BOOTLOADER) + devicever = EROSQN_VER; +#else + devicever = device_data.hw_rev; +#endif + if (devicever >= 4){ + return axp2101_egauge_read(); + } else { + return -1; + } +} + int _battery_voltage(void) { int devicever;