From 4506f2b58d533a5cf0055f43d234a19fa3ae2bdb Mon Sep 17 00:00:00 2001 From: Aidan MacDonald Date: Sun, 12 Dec 2021 12:30:50 +0000 Subject: powermgmt: Refactor battery measurement code I've tried to clean up cruft and clarify what's being done, prior to adding new features. The behavior should be unchanged. Change-Id: If8a68b7b48173d283df981a21cdd854b714e7695 --- firmware/powermgmt.c | 510 +++++++++++++++++-------------------- uisimulator/common/powermgmt-sim.c | 45 ++-- 2 files changed, 266 insertions(+), 289 deletions(-) diff --git a/firmware/powermgmt.c b/firmware/powermgmt.c index 13e810e926..25a9a127e7 100644 --- a/firmware/powermgmt.c +++ b/firmware/powermgmt.c @@ -52,11 +52,7 @@ #include "pcf50606.h" #endif -/** Shared by sim **/ static int last_sent_battery_level = 100; -/* battery level (0-100%) */ -int battery_percent = -1; -void send_battery_level_event(void); static void set_sleep_timer(int seconds); static bool sleeptimer_active = false; @@ -83,41 +79,6 @@ void handle_auto_poweroff(void); static int poweroff_timeout = 0; static long last_event_tick = 0; -#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE -#ifdef SIMULATOR -int _battery_level(void) { return -1; } -#endif -#else -int _battery_level(void) { return -1; } -#endif - -#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE -/* - * Average battery voltage and charger voltage, filtered via a digital - * exponential filter (aka. exponential moving average, scaled): - * avgbat = y[n] = (N-1)/N*y[n-1] + x[n]. battery_millivolts = y[n] / N. - */ -static unsigned int avgbat; -/* filtered battery voltage, millivolts */ -static unsigned int battery_millivolts; -#else -#ifndef SIMULATOR -int _battery_voltage(void) { return -1; } -const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11]; -const unsigned short percent_to_volt_charge[11]; -#endif -#endif - -#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) -#ifdef CURRENT_NORMAL -static int powermgmt_est_runningtime_min; -int _battery_time(void) { return powermgmt_est_runningtime_min; } -#else -int _battery_time(void) { return -1; } -#endif -#endif - -/* default value, mAh */ #if BATTERY_CAPACITY_INC > 0 static int battery_capacity = BATTERY_CAPACITY_DEFAULT; #else @@ -141,82 +102,190 @@ static char power_stack[DEFAULT_STACK_SIZE/2]; #endif static const char power_thread_name[] = "power"; +#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) +int _battery_level(void) { return -1; } +#endif +static int percent_now; /* Cached to avoid polling too often */ -static int voltage_to_battery_level(int battery_millivolts); -static void battery_status_update(void); - -#if BATTERY_TYPES_COUNT > 1 -void set_battery_type(int type) -{ - if (type != battery_type) { - if ((unsigned)type >= BATTERY_TYPES_COUNT) - type = 0; +#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) +int _battery_time(void) { return -1; } +#endif +#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL) +static int time_now; /* Cached to avoid polling too often */ +#endif - battery_type = type; - battery_status_update(); /* recalculate the battery status */ - } -} +#if !(CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE) +int _battery_voltage(void) { return -1; } +#else +/* Data for the digital exponential filter */ +static int voltage_avg, voltage_now; #endif -#if BATTERY_CAPACITY_INC > 0 -void set_battery_capacity(int capacity) +/* 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 + * will be used instead of voltage-based estimation. */ +int battery_level(void) { - if (capacity > BATTERY_CAPACITY_MAX) - capacity = BATTERY_CAPACITY_MAX; - if (capacity < BATTERY_CAPACITY_MIN) - capacity = BATTERY_CAPACITY_MIN; - - battery_capacity = capacity; +#ifdef HAVE_BATTERY_SWITCH + if ((power_input_status() & POWER_INPUT_BATTERY) == 0) + return -1; +#endif - battery_status_update(); /* recalculate the battery status */ + return percent_now; } + +/* The time remaining to full charge/discharge can be provided by the + * target if it has an accurate way of doing this. Otherwise, if the + * target defines a valid battery capacity and can report the charging + * and discharging current, the time remaining will be estimated based + * on the battery level and the actual current usage. */ +int battery_time(void) +{ +#if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) || defined(CURRENT_NORMAL) + return time_now; +#else + return -1; #endif +} -int get_battery_capacity(void) +/* Battery voltage should always be reported if available, but it is + * optional if the the target reports battery percentage directly. */ +int battery_voltage(void) { - return battery_capacity; +#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE + return voltage_now; +#else + return -1; +#endif } -int battery_time(void) +/* Battery current can be estimated if the target defines CURRENT_NORMAL + * as the number of milliamps usually consumed by the device in a normal + * state. The target can also define other CURRENT_* values to estimate + * the power consumed by the backlight, remote display, SPDIF, etc. */ +int battery_current(void) { -#if !(CONFIG_BATTERY_MEASURE & TIME_MEASURE) - /* Note: This should not really be possible but it might occur - * as a degenerate case for targets that don't define any battery - * capacity at all..? */ - if(battery_capacity <= 0) - return -1; +#if defined(CURRENT_NORMAL) + int current = CURRENT_NORMAL; + +#ifndef BOOTLOADER + if (usb_inserted() +#ifdef HAVE_USB_POWER + #if (CURRENT_USB < CURRENT_NORMAL) + || usb_powered_only() + #else + && !usb_powered_only() + #endif +#endif + ) { + current = CURRENT_USB; + } + +#if defined(HAVE_BACKLIGHT) && defined(CURRENT_BACKLIGHT) + if (backlight_get_current_timeout() == 0) /* LED always on */ + current += CURRENT_BACKLIGHT; +#endif + +#if defined(HAVE_RECORDING) && defined(CURRENT_RECORD) + if (audio_status() & AUDIO_STATUS_RECORD) + current += CURRENT_RECORD; +#endif + +#if defined(HAVE_SPDIF_POWER) && defined(CURRENT_SPDIF_OUT) + if (spdif_powered()) + current += CURRENT_SPDIF_OUT; #endif - return _battery_time(); +#if defined(HAVE_REMOTE_LCD) && defined(CURRENT_REMOTE) + if (remote_detect()) + current += CURRENT_REMOTE; +#endif + +#if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA) + if (ide_powered()) + current += CURRENT_ATA; +#endif + +#if CONFIG_CHARGING >= CHARGING_MONITOR + /* While charging we must report the charging current. */ + if (charging_state()) { + current = CURRENT_MAX_CHG - current; + current = MIN(current, 1); + } +#endif + +#endif /* BOOTLOADER */ + + return current; +#else + return -1; +#endif } -/* Returns battery level in percent */ -int battery_level(void) +/* Initialize the battery voltage filter. This is called once + * by the power thread before entering the main polling loop. */ +static void average_init(void) { -#ifdef HAVE_BATTERY_SWITCH - if ((power_input_status() & POWER_INPUT_BATTERY) == 0) - return -1; +#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE + voltage_now = _battery_voltage() + 15; + + /* The battery voltage is usually a little lower directly after + turning on, because the disk was used heavily. Raise it by 5% */ +#ifdef HAVE_DISK_STORAGE +#if CONFIG_CHARGING + if(!charger_inserted()) #endif - return battery_percent; + { + voltage_now += (percent_to_volt_discharge[battery_type][6] - + percent_to_volt_discharge[battery_type][5]) / 2; + } +#endif /* HAVE_DISK_STORAGE */ + + voltage_avg = voltage_now * BATT_AVE_SAMPLES; +#endif /* CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE */ } -/* Tells if the battery level is safe for disk writes */ -bool battery_level_safe(void) +/* Sample the battery voltage and update the filter. + * Updated once every POWER_THREAD_STEP_TICKS. */ +static void average_step(bool low_battery) { -#if defined(NO_LOW_BATTERY_SHUTDOWN) - return true; -#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE - return (battery_percent > 0); -#elif defined(HAVE_BATTERY_SWITCH) - /* Cannot rely upon the battery reading to be valid and the - * device could be powered externally. */ - return input_millivolts() > battery_level_dangerous[battery_type]; +#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE + int millivolts = _battery_voltage(); + if(low_battery) { + voltage_now = (millivolts + voltage_now + 1) / 2; + voltage_avg += voltage_now - voltage_avg / BATT_AVE_SAMPLES; + } else { + voltage_avg += millivolts - voltage_avg / BATT_AVE_SAMPLES; + voltage_now = voltage_avg / BATT_AVE_SAMPLES; + } #else - return battery_millivolts > battery_level_dangerous[battery_type]; + (void)low_battery; #endif } -/* look into the percent_to_volt_* table and get a realistic battery level */ +/* Send system battery level update events on reaching certain significant + * levels. This is called by battery_status_update() and does not have to + * be called separately. */ +static void send_battery_level_event(int percent) +{ + static const int levels[] = { 5, 15, 30, 50, 0 }; + const int *level = levels; + + while (*level) + { + if (percent <= *level && last_sent_battery_level > *level) { + last_sent_battery_level = *level; + queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level); + break; + } + + level++; + } +} + +#if !(CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE) +/* Look into the percent_to_volt_* table and estimate the battery level. */ static int voltage_to_percent(int voltage, const short* table) { if (voltage <= table[0]) { @@ -238,20 +307,19 @@ static int voltage_to_percent(int voltage, const short* table) } } -/* update battery level and estimated runtime, called once per minute or - * when battery capacity / type settings are changed */ -static int voltage_to_battery_level(int battery_millivolts) +/* Convert voltage to a battery level percentage using the appropriate + * percent_to_volt_* lookup table. */ +static int voltage_to_battery_level(int millivolts) { int level; - if (battery_millivolts < 0) + if (millivolts < 0) return -1; #if CONFIG_CHARGING >= CHARGING_MONITOR if (charging_state()) { /* battery level is defined to be < 100% until charging is finished */ - level = voltage_to_percent(battery_millivolts, - percent_to_volt_charge); + level = voltage_to_percent(millivolts, percent_to_volt_charge); if (level > 99) level = 99; } @@ -259,105 +327,98 @@ static int voltage_to_battery_level(int battery_millivolts) #endif /* CONFIG_CHARGING >= CHARGING_MONITOR */ { /* DISCHARGING or error state */ - level = voltage_to_percent(battery_millivolts, - percent_to_volt_discharge[battery_type]); + level = voltage_to_percent(millivolts, percent_to_volt_discharge[battery_type]); } return level; } +#endif +/* Update battery percentage and time remaining information. + * + * This will be called by the power thread after polling new battery data. + * It must also be called if the battery type or capacity changes. + */ static void battery_status_update(void) { - int millivolt = battery_voltage(); +#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE int level = _battery_level(); +#elif CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE + int level = voltage_to_battery_level(voltage_now); +#else + /* This should be a compile time error? */ + int level = -1; +#endif - if (level < 0) - level = voltage_to_battery_level(millivolt); - -#ifdef CURRENT_NORMAL +#if CONFIG_BATTERY_MEASURE & TIME_MEASURE + time_now = _battery_time(); +#elif defined(CURRENT_NORMAL) int current = battery_current(); - + if(level >= 0 && current > 0 && battery_capacity > 0) { #if CONFIG_CHARGING >= CHARGING_MONITOR - if (charging_state()) { - /* charging: remaining charging time */ - if(current > 0) { - powermgmt_est_runningtime_min = - (100 - level) * battery_capacity * 60 / 100 / current; - } + if (charging_state()) + time_now = (100 - level) * battery_capacity * 60 / 100 / current; + else +#endif + time_now = (level + percent_now) * battery_capacity * 60 / 200 / current; + } else { + /* not enough information to calculate time remaining */ + time_now = -1; } - else -#endif - - /* discharging: remaining running time */ - if (level >= 0 && current > 0) { - powermgmt_est_runningtime_min = - (level + battery_percent) * battery_capacity * 60 / 200 / current; - } - - if (powermgmt_est_runningtime_min < 0 || current <= 0) - powermgmt_est_runningtime_min = 0; #endif - battery_percent = level; - send_battery_level_event(); + percent_now = level; + send_battery_level_event(level); } -#ifdef CURRENT_NORMAL -int battery_current(void) +#if BATTERY_TYPES_COUNT > 1 +void set_battery_type(int type) { - int current = CURRENT_NORMAL; + if(type < 0 || type > BATTERY_TYPES_COUNT) + type = 0; -#ifndef BOOTLOADER - if (usb_inserted() -#ifdef HAVE_USB_POWER - #if (CURRENT_USB < CURRENT_NORMAL) - || usb_powered_only() - #else - && !usb_powered_only() - #endif -#endif - ) { - current = CURRENT_USB; + if (type != battery_type) { + battery_type = type; + battery_status_update(); /* recalculate the battery status */ } - -#if defined(HAVE_BACKLIGHT) && defined(CURRENT_BACKLIGHT) - if (backlight_get_current_timeout() == 0) /* LED always on */ - current += CURRENT_BACKLIGHT; -#endif - -#if defined(HAVE_RECORDING) && defined(CURRENT_RECORD) - if (audio_status() & AUDIO_STATUS_RECORD) - current += CURRENT_RECORD; -#endif - -#if defined(HAVE_SPDIF_POWER) && defined(CURRENT_SPDIF_OUT) - if (spdif_powered()) - current += CURRENT_SPDIF_OUT; -#endif - -#if defined(HAVE_REMOTE_LCD) && defined(CURRENT_REMOTE) - if (remote_detect()) - current += CURRENT_REMOTE; +} #endif -#if defined(HAVE_ATA_POWER_OFF) && defined(CURRENT_ATA) - if (ide_powered()) - current += CURRENT_ATA; -#endif +#if BATTERY_CAPACITY_INC > 0 +void set_battery_capacity(int capacity) +{ + if (capacity > BATTERY_CAPACITY_MAX) + capacity = BATTERY_CAPACITY_MAX; + if (capacity < BATTERY_CAPACITY_MIN) + capacity = BATTERY_CAPACITY_MIN; -#if CONFIG_CHARGING >= CHARGING_MONITOR - /* While charging we must report the charging current. */ - if (charging_state()) { - current = CURRENT_MAX_CHG - current; - current = MIN(current, 1); + if (capacity != battery_capacity) { + battery_capacity = capacity; + battery_status_update(); /* recalculate the battery status */ } +} #endif -#endif /* BOOTLOADER */ +int get_battery_capacity(void) +{ + return battery_capacity; +} - return current; +/* Tells if the battery level is safe for disk writes */ +bool battery_level_safe(void) +{ +#if defined(NO_LOW_BATTERY_SHUTDOWN) + return true; +#elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE + return percent_now > 0; +#elif defined(HAVE_BATTERY_SWITCH) + /* Cannot rely upon the battery reading to be valid and the + * device could be powered externally. */ + return input_millivolts() > battery_level_dangerous[battery_type]; +#else + return voltage_now > battery_level_dangerous[battery_type]; +#endif } -#endif /* CURRENT_NORMAL */ /* Check to see whether or not we've received an alarm in the last second */ #ifdef HAVE_RTC_ALARM @@ -374,13 +435,13 @@ bool query_force_shutdown(void) #if defined(NO_LOW_BATTERY_SHUTDOWN) return false; #elif CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE - return battery_percent == 0; + return percent_now == 0; #elif defined(HAVE_BATTERY_SWITCH) /* Cannot rely upon the battery reading to be valid and the * device could be powered externally. */ return input_millivolts() < battery_level_shutoff[battery_type]; #else - return battery_millivolts < battery_level_shutoff[battery_type]; + return voltage_now < battery_level_shutoff[battery_type]; #endif } @@ -391,8 +452,8 @@ bool query_force_shutdown(void) */ void reset_battery_filter(int millivolts) { - avgbat = millivolts * BATT_AVE_SAMPLES; - battery_millivolts = millivolts; + voltage_avg = millivolts * BATT_AVE_SAMPLES; + voltage_now = millivolts; battery_status_update(); } #endif /* HAVE_BATTERY_SWITCH */ @@ -529,88 +590,14 @@ static inline bool detect_charger(unsigned int pwr) #if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE -/* Returns filtered battery voltage [millivolts] */ -int battery_voltage(void) -{ - return battery_millivolts; -} - -static void average_init(void) -{ - /* initialize the voltages for the exponential filter */ - avgbat = _battery_voltage() + 15; - -#ifdef HAVE_DISK_STORAGE /* this adjustment is only needed for HD based */ - /* The battery voltage is usually a little lower directly after - turning on, because the disk was used heavily. Raise it by 5% */ -#if CONFIG_CHARGING - if (!charger_inserted()) /* only if charger not connected */ -#endif - { - avgbat += (percent_to_volt_discharge[battery_type][6] - - percent_to_volt_discharge[battery_type][5]) / 2; - } -#endif /* HAVE_DISK_STORAGE */ - - avgbat = avgbat * BATT_AVE_SAMPLES; - battery_millivolts = power_history[0] = avgbat / BATT_AVE_SAMPLES; -} - -static void average_step(void) -{ - avgbat += _battery_voltage() - avgbat / BATT_AVE_SAMPLES; - /* - * battery_millivolts is the millivolt-scaled filtered battery value. - */ - battery_millivolts = avgbat / BATT_AVE_SAMPLES; -} - -static void average_step_low(void) -{ - battery_millivolts = (_battery_voltage() + battery_millivolts + 1) / 2; - avgbat += battery_millivolts - avgbat / BATT_AVE_SAMPLES; -} - -static void init_battery_percent(void) -{ -#if CONFIG_CHARGING - if (charger_inserted()) { - battery_percent = voltage_to_percent(battery_millivolts, - percent_to_volt_charge); - } - else -#endif - { - battery_percent = voltage_to_percent(battery_millivolts, - percent_to_volt_discharge[battery_type]); - battery_percent += battery_percent < 100; - } - -} - static int power_hist_item(void) { - return battery_millivolts; + return voltage_now; } -#define power_history_unit() battery_millivolts - #else -int battery_voltage(void) -{ - return -1; -} - -static void average_init(void) {} -static void average_step(void) {} -static void average_step_low(void) {} -static void init_battery_percent(void) -{ - battery_percent = _battery_level(); -} - static int power_hist_item(void) { - return battery_percent; + return percent_now; } #endif @@ -651,13 +638,11 @@ static inline void power_thread_step(void) || charger_input_state == CHARGER #endif ) { - average_step(); - /* update battery status every time an update is available */ + average_step(false); battery_status_update(); } - else if (battery_percent < 8) { - average_step_low(); - /* update battery status every time an update is available */ + else if (percent_now < 8) { + average_step(true); battery_status_update(); /* @@ -703,7 +688,7 @@ static void power_thread(void) /* initialize voltage averaging (if available) */ average_init(); /* get initial battery level value (in %) */ - init_battery_percent(); + battery_status_update(); /* get some initial data for the power curve */ collect_power_history(); @@ -848,25 +833,6 @@ void cancel_shutdown(void) shutdown_timeout = 0; } -/* Send system battery level update events on reaching certain significant - levels. This must be called after battery_percent has been updated. */ -void send_battery_level_event(void) -{ - static const int levels[] = { 5, 15, 30, 50, 0 }; - const int *level = levels; - - while (*level) - { - if (battery_percent <= *level && last_sent_battery_level > *level) { - last_sent_battery_level = *level; - queue_broadcast(SYS_BATTERY_UPDATE, last_sent_battery_level); - break; - } - - level++; - } -} - void set_sleeptimer_duration(int minutes) { set_sleep_timer(minutes * 60); diff --git a/uisimulator/common/powermgmt-sim.c b/uisimulator/common/powermgmt-sim.c index 511648bc9d..5d669bcae2 100644 --- a/uisimulator/common/powermgmt-sim.c +++ b/uisimulator/common/powermgmt-sim.c @@ -39,9 +39,10 @@ #define POWER_AFTER_CHARGE_TICKS (8 * HZ) #endif -extern int battery_percent; static bool charging = false; -static unsigned int battery_millivolts = BATT_MAXMVOLT; +static unsigned int batt_millivolts = BATT_MAXMVOLT; +static unsigned int batt_percent = 100; +static unsigned int batt_runtime = BATT_MAXRUNTIME; void powermgmt_init_target(void) {} @@ -54,7 +55,7 @@ static void battery_status_update(void) static unsigned int ext_power_until_tick = 0; #endif - if TIME_BEFORE(current_tick, update_after_tick) + if(TIME_BEFORE(current_tick, update_after_tick)) return; update_after_tick = current_tick + HZ; @@ -72,10 +73,9 @@ static void battery_status_update(void) #endif if (charging) { - battery_millivolts += BATT_CHARGE_STEP; - if (battery_millivolts >= BATT_MAXMVOLT) { + batt_millivolts += BATT_CHARGE_STEP; + if (batt_millivolts >= BATT_MAXMVOLT) { charging = false; - battery_percent = 100; #if CONFIG_CHARGING >= CHARGING_MONITOR /* Keep external power until tick */ ext_power_until_tick = current_tick + POWER_AFTER_CHARGE_TICKS; @@ -83,23 +83,20 @@ static void battery_status_update(void) /* Pretend the charger was disconnected */ charger_input_state = CHARGER_UNPLUGGED; #endif - return; } } else { - battery_millivolts -= BATT_DISCHARGE_STEP; - if (battery_millivolts <= BATT_MINMVOLT) { + batt_millivolts -= BATT_DISCHARGE_STEP; + if (batt_millivolts <= BATT_MINMVOLT) { charging = true; - battery_percent = 0; #if CONFIG_CHARGING /* Pretend the charger was connected */ charger_input_state = CHARGER_PLUGGED; #endif - return; } } - battery_percent = 100 * (battery_millivolts - BATT_MINMVOLT) / - (BATT_MAXMVOLT - BATT_MINMVOLT); + batt_percent = (batt_millivolts - BATT_MINMVOLT) / (BATT_MAXMVOLT - BATT_MINMVOLT); + batt_runtime = batt_percent * BATT_MAXRUNTIME; } const unsigned short battery_level_dangerous[BATTERY_TYPES_COUNT] = { 3200 }; @@ -111,15 +108,28 @@ const unsigned short percent_to_volt_discharge[BATTERY_TYPES_COUNT][11] = const unsigned short percent_to_volt_charge[11] = { 3300, 3400, 3500, 3600, 3700, 3800, 3900, 4000, 4100, 4200, 4300 }; +#if CONFIG_BATTERY_MEASURE & VOLTAGE_MEASURE int _battery_voltage(void) { battery_status_update(); - return battery_millivolts; + return batt_millivolts; } +#endif + +#if CONFIG_BATTERY_MEASURE & PERCENTAGE_MEASURE +int _battery_level(void) +{ + battery_status_update(); + return batt_percent; +} +#endif #if (CONFIG_BATTERY_MEASURE & TIME_MEASURE) -static int powermgmt_est_runningtime_min; -int _battery_time(void) { return powermgmt_est_runningtime_min; } +int _battery_time(void) +{ + battery_status_update(); + return batt_runtime; +} #endif #if CONFIG_CHARGING @@ -169,6 +179,7 @@ unsigned int input_millivolts(void) /* Just return a safe value if battery isn't connected */ return 4050; } - return battery_voltage();; + + return battery_voltage(); } #endif -- cgit v1.2.3