Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Max17055 improvements #2197

Merged
merged 12 commits into from
Jul 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions firmware/application/apps/ui_battinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,13 @@

#include "event_m0.hpp"
#include "portapack.hpp"

#include "battery.hpp"
#include <cstring>

using namespace portapack;

namespace ui {

bool BattinfoView::needRun = true;
void BattinfoView::focus() {
button_exit.focus();
}
Expand All @@ -53,23 +52,24 @@ void BattinfoView::update_result() {
return;
}
bool uichg = false;
battery::BatteryManagement::getBatteryInfo(percent, voltage, current);
uint8_t valid_mask = 0;
battery::BatteryManagement::getBatteryInfo(valid_mask, percent, voltage, current);
// update text fields
if (percent <= 100)
if (percent <= 100 && (valid_mask & battery::BatteryManagement::BATT_VALID_VOLTAGE) == battery::BatteryManagement::BATT_VALID_VOLTAGE)
text_percent.set(to_string_dec_uint(percent) + " %");
else
text_percent.set("UNKNOWN");
if (voltage > 1) {
if (voltage > 1 && (valid_mask & battery::BatteryManagement::BATT_VALID_VOLTAGE) == battery::BatteryManagement::BATT_VALID_VOLTAGE) {
text_voltage.set(to_string_decimal(voltage / 1000.0, 3) + " V");
} else {
text_voltage.set("UNKNOWN");
}
if (current != 0) {
if ((valid_mask & battery::BatteryManagement::BATT_VALID_CURRENT) == battery::BatteryManagement::BATT_VALID_CURRENT) {
if (labels_opt.hidden()) uichg = true;
labels_opt.hidden(false);
text_current.hidden(false);
text_charge.hidden(false);
text_current.set(to_string_decimal(current / 100000.0, 3) + " mA");
text_current.set(to_string_dec_int(current) + " mA");
text_charge.set(current >= 0 ? "Charging" : "Discharging");
labels_opt.hidden(false);
} else {
Expand All @@ -80,7 +80,7 @@ void BattinfoView::update_result() {
}
if (uichg) set_dirty();
// to update status bar too, send message in behalf of batt manager
BatteryStateMessage msg{percent, current >= 0, voltage};
BatteryStateMessage msg{valid_mask, percent, current >= 0, voltage};
EventDispatcher::send_message(msg);
}

Expand All @@ -99,21 +99,19 @@ BattinfoView::BattinfoView(NavigationView& nav)
};

update_result();
needRun = true;
thread = chThdCreateFromHeap(NULL, 512, NORMALPRIO + 10, BattinfoView::static_fn, this);
if (thread == nullptr) thread = chThdCreateFromHeap(NULL, 1024, NORMALPRIO + 10, BattinfoView::static_fn, this);
}

msg_t BattinfoView::static_fn(void* arg) {
auto obj = static_cast<BattinfoView*>(arg);
while (needRun) {
while (!chThdShouldTerminate()) {
chThdSleepMilliseconds(16);
obj->on_timer();
}
return 0;
}

BattinfoView::~BattinfoView() {
needRun = false;
if (thread) {
chThdTerminate(thread);
chThdWait(thread);
Expand Down
1 change: 0 additions & 1 deletion firmware/application/apps/ui_battinfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,6 @@ class BattinfoView : public View {
{72, 17 * 16, 96, 32},
"Back"};
static msg_t static_fn(void* arg);
static bool needRun;
Thread* thread{nullptr};
};

Expand Down
14 changes: 10 additions & 4 deletions firmware/application/ui_navigation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,16 @@ void SystemStatusView::on_battery_details() {
}

void SystemStatusView::on_battery_data(const BatteryStateMessage* msg) {
if (!batt_was_inited) {
batt_was_inited = true;
refresh();
return;
}
if (!pmem::ui_hide_numeric_battery()) {
battery_text.set_battery(msg->percent, msg->on_charger);
battery_text.set_battery(msg->valid_mask, msg->percent, msg->on_charger);
}
if (!pmem::ui_hide_battery_icon()) {
battery_icon.set_battery(msg->percent, msg->on_charger);
battery_icon.set_battery(msg->valid_mask, msg->percent, msg->on_charger);
};
}

Expand All @@ -410,14 +415,15 @@ void SystemStatusView::refresh() {

if (!pmem::ui_hide_fake_brightness()) status_icons.add(&button_fake_brightness);
if (battery::BatteryManagement::isDetected()) {
batt_was_inited = true;
uint8_t percent = battery::BatteryManagement::getPercent();
if (!pmem::ui_hide_battery_icon()) {
status_icons.add(&battery_icon);
battery_text.set_battery(percent, false); // got an on select, that may pop up the details of the battery.
battery_text.set_battery(percent <= 100 ? 1 : 0, percent, false); // got an on select, that may pop up the details of the battery.
};
if (!pmem::ui_hide_numeric_battery()) {
status_icons.add(&battery_text);
battery_text.set_battery(percent, false);
battery_text.set_battery(percent <= 100 ? 1 : 0, percent, false);
}
}

Expand Down
3 changes: 2 additions & 1 deletion firmware/application/ui_navigation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,8 @@ class SystemStatusView : public View {

private:
static constexpr auto default_title = "";
bool batt_info_up = false; // to prevent show multiple batt info dialog
bool batt_was_inited = false; // if the battery was off on tart, but later turned on.
bool batt_info_up = false; // to prevent show multiple batt info dialog
NavigationView& nav_;

Rectangle backdrop{
Expand Down
3 changes: 2 additions & 1 deletion firmware/common/ads1110.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ uint16_t ADS1110::readVoltage() {
return (uint16_t)voltage;
}

void ADS1110::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage) {
void ADS1110::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage) {
voltage = readVoltage();

// Calculate the remaining battery percentage
Expand All @@ -127,6 +127,7 @@ void ADS1110::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage) {
// 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
}

} /* namespace ads1110 */
Expand Down
2 changes: 1 addition & 1 deletion firmware/common/ads1110.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ADS1110 {
bool isDetected() const { return detected_; }

uint16_t readVoltage();
void getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage);
void getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage);

private:
I2C& bus;
Expand Down
56 changes: 35 additions & 21 deletions firmware/common/battery.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,55 @@ extern I2C portapack::i2c0;

namespace battery {

constexpr uint32_t BATTERY_UPDATE_INTERVAL = 30000;
constexpr uint32_t BATTERY_UPDATE_INTERVAL = 20000;
BatteryManagement::BatteryModules BatteryManagement::detected_ = BatteryManagement::BATT_NONE;

ads1110::ADS1110 battery_ads1110{portapack::i2c0, 0x48};
max17055::MAX17055 battery_max17055{portapack::i2c0, 0x36};

Thread* BatteryManagement::thread = nullptr;

void BatteryManagement::init() {
void BatteryManagement::detect() {
// try to detect supported modules
detected_ = BATT_NONE;
if (battery_ads1110.detect()) {
battery_ads1110.init();
detected_ = BATT_ADS1110;
} else if (battery_max17055.detect()) {
battery_max17055.init();
return;
}
if (battery_max17055.detect()) {
// battery_max17055.init(); //detect will call this on each "re detect"
detected_ = BATT_MAX17055;
return;
}

// add new supported module detect + init here

#ifdef USE_BATT_EMULATOR
if (detected_ == BATT_NONE) {
detected_ = BATT_EMULATOR;
return;
}
#endif
}

if (detected_ != BATT_NONE) {
// sets timer to query and broadcats this info
create_thread();
}
void BatteryManagement::init() {
detect();
// sets timer to query and broadcats this info
create_thread();
}

// sets the values, it the currend module supports it.
bool BatteryManagement::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current) {
void BatteryManagement::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current) {
if (detected_ == BATT_NONE) {
return false;
valid_mask = BATT_VALID_NONE;
return;
} else if (detected_ == BATT_ADS1110) {
battery_ads1110.getBatteryInfo(batteryPercentage, voltage);
return true;
battery_ads1110.getBatteryInfo(valid_mask, batteryPercentage, voltage);
return;
} else if (detected_ == BATT_MAX17055) {
battery_max17055.getBatteryInfo(batteryPercentage, voltage, current);
return true;
battery_max17055.getBatteryInfo(valid_mask, batteryPercentage, voltage, current);
return;
}
// add new module query here

Expand All @@ -64,12 +70,12 @@ bool BatteryManagement::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& vol
voltage = rand() % 1000 + 3000; // mV
current = rand() % 150; // mA
isCharging = rand() % 2;
valid_mask = 3;
return true;
}
#endif

(void)current;
return false;
}

uint16_t BatteryManagement::read_register(const uint8_t reg) {
Expand All @@ -88,34 +94,42 @@ bool BatteryManagement::write_register(const uint8_t reg, const uint16_t value)

uint8_t BatteryManagement::getPercent() {
if (detected_ == BATT_NONE) return 102;
uint8_t validity = 0;
uint8_t batteryPercentage = 0;
uint16_t voltage = 0;
int32_t current = 0;
getBatteryInfo(batteryPercentage, voltage, current);
getBatteryInfo(validity, batteryPercentage, voltage, current);
if ((validity & BATT_VALID_VOLTAGE) != BATT_VALID_VOLTAGE) return 102;
return batteryPercentage;
}

uint16_t BatteryManagement::getVoltage() {
if (detected_ == BATT_NONE) return 0;
if (detected_ == BATT_NONE) return 102;
uint8_t validity = 0;
uint8_t batteryPercentage = 0;
uint16_t voltage = 0;
int32_t current = 0;
getBatteryInfo(batteryPercentage, voltage, current);
getBatteryInfo(validity, batteryPercentage, voltage, current);
if ((validity & BATT_VALID_VOLTAGE) != BATT_VALID_VOLTAGE) return 0;
return voltage;
}

msg_t BatteryManagement::timer_fn(void* arg) {
(void)arg;
if (!detected_) return 0;
uint8_t validity = 0;
uint8_t batteryPercentage = 102;
uint16_t voltage = 0;
int32_t current = 0;
chThdSleepMilliseconds(1000); // wait ui for fully load
while (1) {
if (BatteryManagement::getBatteryInfo(batteryPercentage, voltage, current)) {
if (!detected_) {
detect(); // try to detect it again, it maybe disconnected while pp was powered up
chThdSleepMilliseconds(500);
}
if (detected_) {
BatteryManagement::getBatteryInfo(validity, batteryPercentage, voltage, current);
// send local message
BatteryStateMessage msg{batteryPercentage, current >= 0, voltage};
BatteryStateMessage msg{validity, batteryPercentage, current >= 0, voltage};
EventDispatcher::send_message(msg);
}
chThdSleepMilliseconds(BATTERY_UPDATE_INTERVAL);
Expand Down
8 changes: 7 additions & 1 deletion firmware/common/battery.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,16 @@ class BatteryManagement {
BATT_MAX17055 = 2,
BATT_EMULATOR = 254
};
enum BatteryValidMask {
BATT_VALID_NONE = 0,
BATT_VALID_VOLTAGE = 1,
BATT_VALID_CURRENT = 2,
};
static void init();
static void detect();
static bool isDetected() { return detected_ != BATT_NONE; }
static BatteryModules detectedModule() { return detected_; }
static bool getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current);
static void getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current);
static uint16_t getVoltage();
static uint8_t getPercent();
static uint16_t read_register(const uint8_t reg);
Expand Down
33 changes: 24 additions & 9 deletions firmware/common/max17055.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,8 @@ namespace max17055 {
void MAX17055::init() {
if (!detected_) {
detected_ = detect();
} else {
}
if (detected_) { // check again if it is detected
config();
setHibCFG(0x0000);

Expand Down Expand Up @@ -81,8 +82,15 @@ bool MAX17055::detect() {

// Get Data from IC
if (readMultipleRegister(0x00, _MAX17055_Data, 2, false)) {
detected_ = true;
return true;
if (((_MAX17055_Data[0] != 0x00) && (_MAX17055_Data[0] != 0x02)) || (_MAX17055_Data[1] != 0x00)) {
// validate result, since i2c gives a bit of power to the ic, and sometimes it sets the init value.
// this will return false when the ic is in init state (0x0002), but on the next iteration it'll give the good value
if (detected_ == false) {
detected_ = true;
init();
}
return true;
}
}
detected_ = false;
return false;
Expand Down Expand Up @@ -153,10 +161,17 @@ bool MAX17055::writeMultipleRegister(uint8_t reg, const uint8_t* data, uint8_t l
return false;
}

void MAX17055::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current) {
voltage = averageVoltage();
batteryPercentage = stateOfCharge();
current = instantCurrent();
void MAX17055::getBatteryInfo(uint8_t& valid_mask, uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current) {
detect(); // need to detect again, since user can disconnect the ic anytime, and that could send garbage causing flickering data.
if (detected_) {
voltage = averageVoltage();
batteryPercentage = stateOfCharge();
current = instantCurrent();
valid_mask = 3; // BATT_VALID_VOLTAGE + CURRENT
} else {
// let's indicate the data is wrong. ui will handle this by display UNK values.
valid_mask = 0;
}
}

bool MAX17055::setEmptyVoltage(uint16_t _Empty_Voltage) {
Expand Down Expand Up @@ -553,7 +568,7 @@ int32_t MAX17055::instantCurrent(void) {
// Convert to signed int16_t (two's complement)
int32_t _Signed_Raw = static_cast<int16_t>(_Measurement_Raw);

int32_t _Value = (_Signed_Raw * 15625) / (__MAX17055_Resistor__ * 100);
int32_t _Value = (_Signed_Raw * 15625) / (__MAX17055_Resistor__ * 100) / 100000;

// End Function
return _Value;
Expand All @@ -566,7 +581,7 @@ int32_t MAX17055::averageCurrent(void) {
// Convert to signed int16_t (two's complement)
int32_t _Signed_Raw = static_cast<int16_t>(_Measurement_Raw);

int32_t _Value = (_Signed_Raw * 15625) / (__MAX17055_Resistor__ * 100);
int32_t _Value = (_Signed_Raw * 15625) / (__MAX17055_Resistor__ * 100) / 100000;

// End Function
return _Value;
Expand Down
Loading
Loading