From ad05c872fe1a0d925f478106bfb56e731f3ce53c Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Tue, 30 Nov 2021 14:16:13 +0000 Subject: powermgmt: Add battery current measurement This allows targets to report the actual discharging or charging current if they are able to. Change-Id: I0b538e6ac94346f1434e45f83c8da8c1260a53a3 --- firmware/export/config.h | 2 ++ firmware/export/powermgmt.h | 7 +++++++ firmware/powermgmt.c | 40 ++++++++++++++++++++++++++++++-------- uisimulator/common/powermgmt-sim.c | 11 +++++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/firmware/export/config.h b/firmware/export/config.h index 17bc626a80..2ae7ef2c53 100644 --- a/firmware/export/config.h +++ b/firmware/export/config.h @@ -208,6 +208,8 @@ Usually application ports, and only if the estimation is better that ours (which it probably is) */ +#define CURRENT_MEASURE 8 /* Target can report battery charge and/or + * discharge current */ /* CONFIG_LCD */ #define LCD_SSD1815 1 /* as used by Sansa M200 and others */ #define LCD_S1D15E06 3 /* as used by iRiver H100 series */ diff --git a/firmware/export/powermgmt.h b/firmware/export/powermgmt.h index c6fc3d5bdf..9d4d4e06aa 100644 --- a/firmware/export/powermgmt.h +++ b/firmware/export/powermgmt.h @@ -94,6 +94,11 @@ void powermgmt_init(void) INIT_ATTR; #define BATT_AVE_SAMPLES 128 #endif +#ifndef BATT_CURRENT_AVE_SAMPLES +/* TODO may need tweaking */ +#define BATT_CURRENT_AVE_SAMPLES 16 +#endif + #ifndef POWER_THREAD_STEP_TICKS /* 2HZ sample rate unless otherwise specified */ #define POWER_THREAD_STEP_TICKS (HZ/2) @@ -118,6 +123,8 @@ int battery_current(void); /* battery current in milliamps int _battery_level(void); /* percent */ int _battery_time(void); /* minutes */ int _battery_voltage(void); /* voltage in millivolts */ +int _battery_current(void); /* (dis)charge current in milliamps */ + #if CONFIG_CHARGING >= CHARGING_TARGET void powermgmt_init_target(void); void charging_algorithm_close(void); diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 8c9b17d52b..30d37927ca 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -110,7 +110,8 @@ static int percent_now; /* Cached to avoid polling too often */ #if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) int _battery_time(void) { return -1; } #endif -#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL) +#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || \ + defined(CURRENT_NORMAL) || (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) static int time_now; /* Cached to avoid polling too often */ #endif @@ -121,6 +122,12 @@ int _battery_voltage(void) { return -1; } static int voltage_avg, voltage_now; #endif +#if !(CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) +int _battery_current(void) { return -1; } +#else +static int current_avg, current_now; +#endif + /* The battery level can be obtained in two ways. If the target reports * voltage, the battery level can be estminated using percent_to_volt_* * curves. If the target can report the percentage directly, then that @@ -142,7 +149,8 @@ int battery_level(void) * on the battery level and the actual current usage. */ int battery_time(void) { -#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL) +#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || \ + defined(CURRENT_NORMAL) || (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) return time_now; #else return -1; @@ -166,7 +174,9 @@ int battery_voltage(void) * the power consumed by the backlight, remote display, SPDIF, etc. */ int battery_current(void) { -#if defined(CURRENT_NORMAL) +#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE + return current_now; +#elif defined(CURRENT_NORMAL) int current = CURRENT_NORMAL; #ifndef BOOTLOADER @@ -223,8 +233,8 @@ int battery_current(void) #endif } -/* Initialize the battery voltage filter. This is called once - * by the power thread before entering the main polling loop. */ +/* Initialize the battery voltage/current filters. This is called + * once by the power thread before entering the main polling loop. */ static void average_init(void) { #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE @@ -244,9 +254,14 @@ static void average_init(void) voltage_avg = voltage_now * BATT_AVE_SAMPLES; #endif /* CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE */ + +#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE + current_now = _battery_current(); + current_avg = current_now * BATT_CURRENT_AVE_SAMPLES; +#endif } -/* Sample the battery voltage and update the filter. +/* Sample the battery voltage/current and update the filters. * Updated once every POWER_THREAD_STEP_TICKS. */ static void average_step(bool low_battery) { @@ -262,6 +277,11 @@ static void average_step(bool low_battery) #else (void)low_battery; #endif + +#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE + current_avg += _battery_current() - current_avg / BATT_CURRENT_AVE_SAMPLES; + current_now = current_avg / BATT_CURRENT_AVE_SAMPLES; +#endif } /* Send system battery level update events on reaching certain significant @@ -353,7 +373,7 @@ static void battery_status_update(void) #if CONFIG_BATTERY_MEASURE & TIME_MEASURE time_now = _battery_time(); -#elif defined(CURRENT_NORMAL) +#elif defined(CURRENT_NORMAL) || (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) int current = battery_current(); if(level >= 0 && current > 0 && battery_capacity > 0) { #if CONFIG_CHARGING >= CHARGING_MONITOR @@ -455,6 +475,11 @@ void reset_battery_filter(int millivolts) { voltage_avg = millivolts * BATT_AVE_SAMPLES; voltage_now = millivolts; +#if CONFIG_BATTERY_MEASURE & CURRENT_MEASURE + /* current would probably be inaccurate too */ + current_now = _battery_current(); + current_avg = current_now * BATT_CURRENT_AVE_SAMPLES; +#endif battery_status_update(); } #endif /* HAVE_BATTERY_SWITCH */ @@ -589,7 +614,6 @@ static inline bool detect_charger(unsigned int pwr) } #endif /* CONFIG_CHARGING */ - #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE static int power_hist_item(void) { diff --git a/uisimulator/common/powermgmt-sim.c b/uisimulator/common/powermgmt-sim.c index 5d669bcae2..1535971e29 100644 --- a/uisimulator/common/powermgmt-sim.c +++ b/uisimulator/common/powermgmt-sim.c @@ -43,6 +43,7 @@ static bool charging = false; static unsigned int batt_millivolts = BATT_MAXMVOLT; static unsigned int batt_percent = 100; static unsigned int batt_runtime = BATT_MAXRUNTIME; +static unsigned int batt_current = 0; void powermgmt_init_target(void) {} @@ -97,6 +98,8 @@ static void battery_status_update(void) batt_percent = (batt_millivolts - BATT_MINMVOLT) / (BATT_MAXMVOLT - BATT_MINMVOLT); batt_runtime = batt_percent * BATT_MAXRUNTIME; + /* current is completely bogus... */ + batt_current = charging ? BATT_CHARGE_STEP : BATT_DISCHARGE_STEP; } const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 }; @@ -132,6 +135,14 @@ int _battery_time(void) } #endif +#if (CONFIG_BATTERY_MEASURE & CURRENT_MEASURE) +int _battery_current(void) +{ + battery_status_update(); + return batt_current; +} +#endif + #if CONFIG_CHARGING unsigned int power_input_status(void) { -- cgit v1.2.3