From 0ae7768f2045e0a21b79a771dcf615239132d240 Mon Sep 17 00:00:00 2001 From: Totoo Date: Wed, 28 Aug 2024 11:32:24 +0200 Subject: [PATCH] Battery info switcher (#2230) --- firmware/application/apps/ui_battinfo.cpp | 22 +++++++++++++- firmware/application/apps/ui_battinfo.hpp | 20 +++++++++---- firmware/application/apps/ui_settings.cpp | 27 +++++++++++++++++ firmware/application/apps/ui_settings.hpp | 29 ++++++++++++++++++ firmware/application/portapack.cpp | 2 +- firmware/common/ads1110.cpp | 12 +------- firmware/common/ads1110.hpp | 2 +- firmware/common/battery.cpp | 30 +++++++++++++++++-- firmware/common/battery.hpp | 10 ++++++- firmware/common/max17055.cpp | 2 +- firmware/common/max17055.hpp | 9 +++--- .../common/portapack_persistent_memory.cpp | 9 +++++- .../common/portapack_persistent_memory.hpp | 2 ++ 13 files changed, 147 insertions(+), 29 deletions(-) diff --git a/firmware/application/apps/ui_battinfo.cpp b/firmware/application/apps/ui_battinfo.cpp index 05bf01249..4dcc38d5a 100644 --- a/firmware/application/apps/ui_battinfo.cpp +++ b/firmware/application/apps/ui_battinfo.cpp @@ -49,6 +49,7 @@ void BattinfoView::update_result() { text_voltage.set("UNKNOWN"); text_current.set("-"); text_charge.set("-"); + text_method.set("-"); return; } bool uichg = false; @@ -78,6 +79,13 @@ void BattinfoView::update_result() { text_current.hidden(true); text_charge.hidden(true); } + if ((valid_mask & battery::BatteryManagement::BATT_VALID_PERCENT) == battery::BatteryManagement::BATT_VALID_PERCENT) { + text_method.set("IC"); + button_mode.set_text("Volt"); + } else { + text_method.set("Voltage"); + button_mode.set_text("IC"); + } if (uichg) set_dirty(); // to update status bar too, send message in behalf of batt manager BatteryStateMessage msg{valid_mask, percent, current >= 0, voltage}; @@ -92,12 +100,24 @@ BattinfoView::BattinfoView(NavigationView& nav) &text_voltage, &text_current, &text_charge, + &text_method, + &button_mode, &button_exit}); button_exit.on_select = [this, &nav](Button&) { nav.pop(); }; - + button_mode.on_select = [this, &nav](Button&) { + if (button_mode.text() == "IC") { + battery::BatteryManagement::set_calc_override(false); + persistent_memory::set_ui_override_batt_calc(false); + button_mode.set_text("Volt"); + } else { + battery::BatteryManagement::set_calc_override(true); + persistent_memory::set_ui_override_batt_calc(true); + button_mode.set_text("IC"); + } + }; update_result(); if (thread == nullptr) thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, BattinfoView::static_fn, this); } diff --git a/firmware/application/apps/ui_battinfo.hpp b/firmware/application/apps/ui_battinfo.hpp index 232a17d90..7500bf471 100644 --- a/firmware/application/apps/ui_battinfo.hpp +++ b/firmware/application/apps/ui_battinfo.hpp @@ -53,11 +53,14 @@ class BattinfoView : public View { Labels labels{ {{2 * 8, 1 * 16}, "Percent:", Theme::getInstance()->fg_light->foreground}, - {{2 * 8, 2 * 16}, "Voltage:", Theme::getInstance()->fg_light->foreground}}; + {{2 * 8, 2 * 16}, "Voltage:", Theme::getInstance()->fg_light->foreground}, + {{2 * 8, 3 * 16}, "Method:", Theme::getInstance()->fg_light->foreground}, + {{2 * 8, 7 * 16}, "Change method:", Theme::getInstance()->fg_light->foreground}, + }; Labels labels_opt{ - {{2 * 8, 3 * 16}, "Current:", Theme::getInstance()->fg_light->foreground}, - {{2 * 8, 4 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground}}; + {{2 * 8, 4 * 16}, "Current:", Theme::getInstance()->fg_light->foreground}, + {{2 * 8, 5 * 16}, "Charge:", Theme::getInstance()->fg_light->foreground}}; Text text_percent{ {13 * 8, 1 * 16, 10 * 16, 16}, @@ -65,12 +68,19 @@ class BattinfoView : public View { Text text_voltage{ {13 * 8, 2 * 16, 10 * 16, 16}, "-"}; - Text text_current{ + Text text_method{ {13 * 8, 3 * 16, 10 * 16, 16}, "-"}; - Text text_charge{ + Text text_current{ {13 * 8, 4 * 16, 10 * 16, 16}, "-"}; + Text text_charge{ + {13 * 8, 5 * 16, 10 * 16, 16}, + "-"}; + + Button button_mode{ + {2 * 8, 8 * 16 + 5, 5 * 16, 32}, + "Volt"}; Button button_exit{ {72, 17 * 16, 96, 32}, diff --git a/firmware/application/apps/ui_settings.cpp b/firmware/application/apps/ui_settings.cpp index 221b3baf9..88752196b 100644 --- a/firmware/application/apps/ui_settings.cpp +++ b/firmware/application/apps/ui_settings.cpp @@ -948,6 +948,32 @@ void SetThemeView::focus() { options.focus(); } +/* SetBatteryView ************************************/ + +SetBatteryView::SetBatteryView(NavigationView& nav) { + add_children({&labels, + &button_save, + &button_cancel, + &checkbox_overridebatt}); + + button_save.on_select = [&nav, this](Button&) { + pmem::set_ui_override_batt_calc(checkbox_overridebatt.value()); + battery::BatteryManagement::set_calc_override(checkbox_overridebatt.value()); + send_system_refresh(); + nav.pop(); + }; + + checkbox_overridebatt.set_value(pmem::ui_override_batt_calc()); + + button_cancel.on_select = [&nav, this](Button&) { + nav.pop(); + }; +} + +void SetBatteryView::focus() { + button_cancel.focus(); +} + /* SettingsMenuView **************************************/ SettingsMenuView::SettingsMenuView(NavigationView& nav) @@ -978,6 +1004,7 @@ void SettingsMenuView::on_populate() { {"Theme", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push(); }}, {"Autostart", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push(); }}, }); + if (battery::BatteryManagement::isDetected()) add_item({"Battery", ui::Color::dark_cyan(), &bitmap_icon_setup, [this]() { nav_.push(); }}); } } /* namespace ui */ diff --git a/firmware/application/apps/ui_settings.hpp b/firmware/application/apps/ui_settings.hpp index 076488517..50dc17bb2 100644 --- a/firmware/application/apps/ui_settings.hpp +++ b/firmware/application/apps/ui_settings.hpp @@ -888,6 +888,35 @@ class SetThemeView : public View { }; }; +class SetBatteryView : public View { + public: + SetBatteryView(NavigationView& nav); + + void focus() override; + + std::string title() const override { return "Battery"; }; + + private: + int32_t selected = 0; + Labels labels{ + {{1 * 8, 1 * 16}, "Override batt calculation", Theme::getInstance()->fg_light->foreground}, + {{1 * 8, 2 * 16}, "method to voltage based", Theme::getInstance()->fg_light->foreground}}; + + Button button_save{ + {2 * 8, 16 * 16, 12 * 8, 32}, + "Save"}; + + Checkbox checkbox_overridebatt{ + {2 * 8, 6 * 16}, + 23, + "Override"}; + + Button button_cancel{ + {16 * 8, 16 * 16, 12 * 8, 32}, + "Cancel", + }; +}; + class SettingsMenuView : public BtnGridView { public: SettingsMenuView(NavigationView& nav); diff --git a/firmware/application/portapack.cpp b/firmware/application/portapack.cpp index b3927f76d..ace69ead8 100644 --- a/firmware/application/portapack.cpp +++ b/firmware/application/portapack.cpp @@ -586,7 +586,7 @@ init_status_t init() { chThdSleepMilliseconds(10); audio::init(portapack_audio_codec()); - battery::BatteryManagement::init(); + battery::BatteryManagement::init(persistent_memory::ui_override_batt_calc()); if (lcd_fast_setup) draw_splash_screen_icon(4, ui::bitmap_icon_speaker); diff --git a/firmware/common/ads1110.cpp b/firmware/common/ads1110.cpp index 921f4afb9..6734b75f9 100644 --- a/firmware/common/ads1110.cpp +++ b/firmware/common/ads1110.cpp @@ -27,9 +27,6 @@ namespace battery { namespace ads1110 { -constexpr uint16_t BATTERY_MIN_VOLTAGE = 3000; -constexpr uint16_t BATTERY_MAX_VOLTAGE = 4000; - void ADS1110::init() { if (!detected_) { detected_ = detect(); @@ -118,15 +115,8 @@ uint16_t ADS1110::readVoltage() { return (uint16_t)voltage; } -void ADS1110::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage) { +void ADS1110::getBatteryInfo(uint8_t& valid_mask, uint16_t& voltage) { voltage = readVoltage(); - - // Calculate the remaining battery percentage - batteryPercentage = (float)(voltage - BATTERY_MIN_VOLTAGE) / (float)(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0; - - // Limit the values to the valid range - batteryPercentage = (batteryPercentage > 100) ? 100 : batteryPercentage; - // ToDo: if its > 4, then 100%, if < 3 then 0% valid_mask = 1; // BATT_VALID_VOLTAGE } diff --git a/firmware/common/ads1110.hpp b/firmware/common/ads1110.hpp index 3c7a626fc..a8014943e 100644 --- a/firmware/common/ads1110.hpp +++ b/firmware/common/ads1110.hpp @@ -42,7 +42,7 @@ class ADS1110 { bool isDetected() const { return detected_; } uint16_t readVoltage(); - void getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage); + void getBatteryInfo(uint8_t& valid_mask, uint16_t& voltage); private: I2C& bus; diff --git a/firmware/common/battery.cpp b/firmware/common/battery.cpp index b89b887f6..cad684fbb 100644 --- a/firmware/common/battery.cpp +++ b/firmware/common/battery.cpp @@ -18,6 +18,7 @@ ads1110::ADS1110 battery_ads1110{portapack::i2c0, 0x48}; max17055::MAX17055 battery_max17055{portapack::i2c0, 0x36}; Thread* BatteryManagement::thread = nullptr; +bool BatteryManagement::calcOverride = false; void BatteryManagement::detect() { // try to detect supported modules @@ -43,22 +44,33 @@ void BatteryManagement::detect() { #endif } -void BatteryManagement::init() { +void BatteryManagement::init(bool override) { + calcOverride = override; detect(); // sets timer to query and broadcats this info create_thread(); } +// set if the default percentage calculation should be overrided by voltage based one +void BatteryManagement::set_calc_override(bool override) { + calcOverride = override; +} + // sets the values, it the currend module supports it. void BatteryManagement::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current) { if (detected_ == BATT_NONE) { valid_mask = BATT_VALID_NONE; return; } else if (detected_ == BATT_ADS1110) { - battery_ads1110.getBatteryInfo(valid_mask, batteryPercentage, voltage); + battery_ads1110.getBatteryInfo(valid_mask, voltage); + batteryPercentage = calc_percent_voltage(voltage); return; } else if (detected_ == BATT_MAX17055) { battery_max17055.getBatteryInfo(valid_mask, batteryPercentage, voltage, current); + if (calcOverride) { + valid_mask &= ~BATT_VALID_PERCENT; // indicate it is voltage based + batteryPercentage = calc_percent_voltage(voltage); + } return; } // add new module query here @@ -70,7 +82,7 @@ void BatteryManagement::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPerc voltage = rand() % 1000 + 3000; // mV current = rand() % 150; // mA isCharging = rand() % 2; - valid_mask = 3; + valid_mask = 7; return true; } #endif @@ -100,6 +112,18 @@ uint8_t BatteryManagement::getPercent() { int32_t current = 0; getBatteryInfo(validity, batteryPercentage, voltage, current); if ((validity & BATT_VALID_VOLTAGE) != BATT_VALID_VOLTAGE) return 102; + if (calcOverride || ((validity & BATT_VALID_PERCENT) != BATT_VALID_PERCENT)) { + validity &= ~BATT_VALID_PERCENT; // indicate it is voltage based + batteryPercentage = calc_percent_voltage(voltage); + } + return batteryPercentage; +} + +uint8_t BatteryManagement::calc_percent_voltage(uint16_t voltage) { + // Calculate the remaining battery percentage + uint8_t batteryPercentage = (float)(voltage - BATTERY_MIN_VOLTAGE) / (float)(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0; + // Limit the values to the valid range + batteryPercentage = (batteryPercentage > 100) ? 100 : batteryPercentage; return batteryPercentage; } diff --git a/firmware/common/battery.hpp b/firmware/common/battery.hpp index c4aaddacd..8146b52fb 100644 --- a/firmware/common/battery.hpp +++ b/firmware/common/battery.hpp @@ -27,6 +27,10 @@ namespace battery { +#define BATTERY_MIN_VOLTAGE 3000.0 +#define BATTERY_MAX_VOLTAGE 4170.0 +#define BATTERY_DESIGN_CAP 2500 + class BatteryManagement { public: enum BatteryModules { @@ -39,8 +43,9 @@ class BatteryManagement { BATT_VALID_NONE = 0, BATT_VALID_VOLTAGE = 1, BATT_VALID_CURRENT = 2, + BATT_VALID_PERCENT = 4, }; - static void init(); + static void init(bool override = false); static void detect(); static bool isDetected() { return detected_ != BATT_NONE; } static BatteryModules detectedModule() { return detected_; } @@ -49,12 +54,15 @@ class BatteryManagement { static uint8_t getPercent(); static uint16_t read_register(const uint8_t reg); static bool write_register(const uint8_t reg, const uint16_t value); + static void set_calc_override(bool override); + static uint8_t calc_percent_voltage(uint16_t); // calculates battery percentage from the voltage private: static void create_thread(); static msg_t timer_fn(void* arg); static Thread* thread; static BatteryModules detected_; // if there is any batt management system + static bool calcOverride; // if set to true, it'll override the battery percent calculation based on current voltage. }; }; // namespace battery #endif \ No newline at end of file diff --git a/firmware/common/max17055.cpp b/firmware/common/max17055.cpp index 2c8f3f994..634ff1c91 100644 --- a/firmware/common/max17055.cpp +++ b/firmware/common/max17055.cpp @@ -166,7 +166,7 @@ void MAX17055::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, u } batteryPercentage = stateOfCharge(); current = instantCurrent(); - valid_mask = 3; // BATT_VALID_VOLTAGE + CURRENT + valid_mask = 7; // BATT_VALID_VOLTAGE + CURRENT + PERCENT } else { // let's indicate the data is wrong. ui will handle this by display UNK values. valid_mask = 0; diff --git a/firmware/common/max17055.hpp b/firmware/common/max17055.hpp index fc4ff97f4..c9a96e314 100644 --- a/firmware/common/max17055.hpp +++ b/firmware/common/max17055.hpp @@ -26,6 +26,7 @@ #include #include +#include "battery.hpp" #include "i2c_pp.hpp" #define MAX17055_POR 0 @@ -47,7 +48,7 @@ // Define Battery Capacity #ifndef __MAX17055_Design_Capacity__ -#define __MAX17055_Design_Capacity__ 2500 // Battery Capacity +#define __MAX17055_Design_Capacity__ BATTERY_DESIGN_CAP // Battery Capacity #endif // Define Gauge Resistor @@ -57,17 +58,17 @@ // Define Minimum Voltage #ifndef __MAX17055_Min_Voltage__ -#define __MAX17055_Min_Voltage__ 3.0 // Minimum Voltage +#define __MAX17055_Min_Voltage__ BATTERY_MIN_VOLTAGE / 1000.0 // Minimum Voltage #endif // Define Maximum Voltage #ifndef __MAX17055_Max_Voltage__ -#define __MAX17055_Max_Voltage__ 4.17 // Maximum Voltage +#define __MAX17055_Max_Voltage__ BATTERY_MAX_VOLTAGE / 1000.0 // Maximum Voltage #endif // Define Empty Voltage #ifndef __MAX17055_Empty_Voltage__ -#define __MAX17055_Empty_Voltage__ 3.0 // Empty Voltage +#define __MAX17055_Empty_Voltage__ BATTERY_MIN_VOLTAGE / 1000.0 // Empty Voltage #endif // Define Recovery Voltage diff --git a/firmware/common/portapack_persistent_memory.cpp b/firmware/common/portapack_persistent_memory.cpp index 866ec45b6..6a24cffe6 100644 --- a/firmware/common/portapack_persistent_memory.cpp +++ b/firmware/common/portapack_persistent_memory.cpp @@ -133,7 +133,7 @@ struct ui_config2_t { bool hide_fake_brightness : 1; bool hide_numeric_battery : 1; bool hide_battery_icon : 1; - bool UNUSED_3 : 1; + bool override_batt_calc : 1; bool UNUSED_4 : 1; bool UNUSED_5 : 1; bool UNUSED_6 : 1; @@ -965,6 +965,10 @@ uint8_t ui_theme_id() { return data->ui_config2.theme_id; } +bool ui_override_batt_calc() { + return data->ui_config2.override_batt_calc; +} + void set_ui_hide_speaker(bool v) { data->ui_config2.hide_speaker = v; } @@ -1006,6 +1010,9 @@ void set_ui_hide_battery_icon(bool v) { void set_ui_theme_id(uint8_t theme_id) { data->ui_config2.theme_id = theme_id; } +void set_ui_override_batt_calc(bool v) { + data->ui_config2.override_batt_calc = v; +} /* Converter */ bool config_converter() { diff --git a/firmware/common/portapack_persistent_memory.hpp b/firmware/common/portapack_persistent_memory.hpp index ae4ec687b..8f512316b 100644 --- a/firmware/common/portapack_persistent_memory.hpp +++ b/firmware/common/portapack_persistent_memory.hpp @@ -339,6 +339,7 @@ bool ui_hide_numeric_battery(); bool ui_hide_battery_icon(); bool ui_hide_sd_card(); uint8_t ui_theme_id(); +bool ui_override_batt_calc(); void set_ui_hide_speaker(bool v); void set_ui_hide_mute(bool v); void set_ui_hide_converter(bool v); @@ -352,6 +353,7 @@ void set_ui_hide_numeric_battery(bool v); void set_ui_hide_battery_icon(bool v); void set_ui_hide_sd_card(bool v); void set_ui_theme_id(uint8_t v); +void set_ui_override_batt_calc(bool v); // sd persisting settings bool should_use_sdcard_for_pmem();