summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-11-30 14:16:13 +0000
committerAidan MacDonald <amachronic@protonmail.com>2021-12-23 11:39:58 +0000
commitad05c872fe1a0d925f478106bfb56e731f3ce53c (patch)
tree156bae0098029e193a9914b6c7049f31efa3805f /firmware
parent923f92cb12ee39364ddec340de140d126ced1347 (diff)
downloadrockbox-ad05c872fe1a0d925f478106bfb56e731f3ce53c.tar.gz
rockbox-ad05c872fe1a0d925f478106bfb56e731f3ce53c.zip
powermgmt: Add battery current measurement
This allows targets to report the actual discharging or charging current if they are able to. Change-Id: I0b538e6ac94346f1434e45f83c8da8c1260a53a3
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/config.h2
-rw-r--r--firmware/export/powermgmt.h7
-rw-r--r--firmware/powermgmt.c40
3 files changed, 41 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)
{