Skip to content

Commit

Permalink
I2C device manager (#2282)
Browse files Browse the repository at this point in the history
* message on dev list change

* dc detect

* added sht3x sensor.

* separete environment data from light

* max17055 moved to i2c dev

* sht fix, goterror detection fix

* fix ext sensor app display for a lot of devices.

* added bh1750 driver

* autoscan on main view

* added devlist mutex

* better timing

* fix h2 sw8 on poweron by usb
  • Loading branch information
htotoo authored Oct 6, 2024
1 parent d4edb5f commit 83b65ba
Show file tree
Hide file tree
Showing 35 changed files with 1,456 additions and 469 deletions.
9 changes: 6 additions & 3 deletions firmware/application/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,9 @@ set(CSRC
${CHIBIOS}/os/various/chprintf.c
)

#look for all i2cdev_ files
file(GLOB I2CDEV_SOURCES ${COMMON}/i2cdev_*.cpp)

# C++ sources that can be compiled in ARM or THUMB mode depending on the global
# setting.
set(CPPSRC
Expand Down Expand Up @@ -176,8 +179,8 @@ set(CPPSRC
${COMMON}/ui_language.cpp
${COMMON}/utility.cpp
${COMMON}/wm8731.cpp
${COMMON}/ads1110.cpp
${COMMON}/max17055.cpp
${COMMON}/i2cdevmanager.cpp
${I2CDEV_SOURCES}
${COMMON}/battery.cpp
${COMMON}/performance_counter.cpp
${COMMON}/bmpfile.cpp
Expand Down Expand Up @@ -292,7 +295,7 @@ set(CPPSRC
apps/ui_btle_rx.cpp
# apps/ui_coasterp.cpp
apps/ui_debug.cpp
apps/ui_debug_battery.cpp
apps/ui_debug_max17055.cpp
apps/ui_dfu_menu.cpp
apps/ui_encoders.cpp
apps/ui_fileman.cpp
Expand Down
151 changes: 87 additions & 64 deletions firmware/application/apps/ui_battinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,87 +43,86 @@ void BattinfoView::on_timer() {
}
}

void BattinfoView::update_result() {
if (!battery::BatteryManagement::isDetected()) {
void BattinfoView::update_results_ads1110(i2cdev::I2cDev_ADS1110* dev) {
bool uichg = false;
auto voltage = dev->readVoltage();
auto percent = battery::BatteryManagement::calc_percent_voltage(voltage);
if (percent <= 100)
text_percent.set(to_string_dec_uint(percent) + " %");
else
text_percent.set("UNKNOWN");
if (voltage > 1) {
text_voltage.set(to_string_decimal(voltage / 1000.0, 3) + " V");
} else {
text_voltage.set("UNKNOWN");
text_current.set("-");
text_charge.set("-");
text_cycles.set("-");
text_ttef.set("-");
text_method.set("-");
text_warn.set("");
return;
}

// ui hide:
if (!labels_opt.hidden()) uichg = true;
labels_opt.hidden(true);
text_current.hidden(true);
text_charge.hidden(true);
labels_opt.hidden(true);
text_ttef.hidden(true);
text_cycles.hidden(true);
text_warn.set("");
text_ttef.hidden(true);
text_method.set("Voltage");
button_mode.set_text("Voltage");
if (uichg) set_dirty();
BatteryStateMessage msg{1, percent, false, voltage};
EventDispatcher::send_message(msg);
}

void BattinfoView::update_results_max17055(i2cdev::I2cDev_MAX17055* dev) {
bool uichg = false;
uint8_t valid_mask = 0;
battery::BatteryManagement::getBatteryInfo(valid_mask, percent, voltage, current);
dev->getBatteryInfo(valid_mask, percent, voltage, current);
// update text fields
if (percent <= 100 && (valid_mask & battery::BatteryManagement::BATT_VALID_VOLTAGE) == battery::BatteryManagement::BATT_VALID_VOLTAGE)
if (percent <= 100)
text_percent.set(to_string_dec_uint(percent) + " %");
else
text_percent.set("UNKNOWN");
if (voltage > 1 && (valid_mask & battery::BatteryManagement::BATT_VALID_VOLTAGE) == battery::BatteryManagement::BATT_VALID_VOLTAGE) {
if (voltage > 1) {
text_voltage.set(to_string_decimal(voltage / 1000.0, 3) + " V");
} else {
text_voltage.set("UNKNOWN");
}
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_dec_int(current) + " mA");
text_charge.set(current >= 0 ? "Charging" : "Discharging");
labels_opt.hidden(false);

text_ttef.hidden(false);
} else {
if (!labels_opt.hidden()) uichg = true;
labels_opt.hidden(true);
text_current.hidden(true);
text_charge.hidden(true);
text_cycles.hidden(true);
text_ttef.hidden(true);
if (labels_opt.hidden()) uichg = true;
labels_opt.hidden(false);
text_current.hidden(false);
text_charge.hidden(false);
text_current.set(to_string_dec_int(current) + " mA");
text_charge.set(current >= 0 ? "Charging" : "Discharging");
labels_opt.hidden(false);
text_ttef.hidden(false);
// cycles
text_cycles.hidden(false);
uint16_t cycles = (uint16_t)dev->getValue("Cycles");
if (cycles < 2)
text_warn.set("SoC improves after 2 cycles");
else
text_warn.set("");
}
if ((valid_mask & battery::BatteryManagement::BATT_VALID_CYCLES) == battery::BatteryManagement::BATT_VALID_CYCLES) {
text_cycles.hidden(false);
uint16_t cycles = battery::BatteryManagement::get_cycles();
if (cycles < 2)
text_warn.set("SoC improves after 2 cycles");
else
text_warn.set("");
text_cycles.set(to_string_dec_uint(cycles));
text_cycles.set(to_string_dec_uint(cycles));
// ttef
text_ttef.hidden(false);
float ttef = 0;
if (current <= 0) {
ttef = dev->getValue("TTE");
} else {
text_cycles.hidden(true);
text_warn.set("");
ttef = dev->getValue("TTF");
}
if ((valid_mask & battery::BatteryManagement::BATT_VALID_TTEF) == battery::BatteryManagement::BATT_VALID_TTEF) {
text_ttef.hidden(false);
float ttef = 0;
if (current <= 0) {
ttef = battery::BatteryManagement::get_tte();
} else {
ttef = battery::BatteryManagement::get_ttf();
}

// Convert ttef to hours and minutes
uint8_t hours = static_cast<uint8_t>(ttef);
uint8_t minutes = static_cast<uint8_t>((ttef - hours) * 60 + 0.5); // +0.5 for rounding

// Create the formatted string
std::string formatted_time;
if (hours > 0) {
formatted_time += to_string_dec_uint(hours) + "h ";
}
formatted_time += to_string_dec_uint(minutes) + "m";

text_ttef.set(formatted_time);
} else {
text_ttef.hidden(true);
// Convert ttef to hours and minutes
uint8_t hours = static_cast<uint8_t>(ttef);
uint8_t minutes = static_cast<uint8_t>((ttef - hours) * 60 + 0.5); // +0.5 for rounding
// Create the formatted string
std::string formatted_time;
if (hours > 0) {
formatted_time += to_string_dec_uint(hours) + "h ";
}
if ((valid_mask & battery::BatteryManagement::BATT_VALID_PERCENT) == battery::BatteryManagement::BATT_VALID_PERCENT) {
formatted_time += to_string_dec_uint(minutes) + "m";
text_ttef.set(formatted_time);
if (!battery::BatteryManagement::calcOverride) {
text_method.set("IC");
button_mode.set_text("Volt");
} else {
Expand All @@ -136,6 +135,30 @@ void BattinfoView::update_result() {
EventDispatcher::send_message(msg);
}

void BattinfoView::update_result() {
auto dev = i2cdev::I2CDevManager::get_dev_by_model(I2CDEVMDL_MAX17055);
if (dev) {
update_results_max17055((i2cdev::I2cDev_MAX17055*)dev);
return;
}

dev = i2cdev::I2CDevManager::get_dev_by_model(I2CDEVMDL_ADS1110);
if (dev) {
update_results_ads1110((i2cdev::I2cDev_ADS1110*)dev);
return;
}

// no dev found
text_percent.set("UNKNOWN");
text_voltage.set("UNKNOWN");
text_current.set("-");
text_charge.set("-");
text_cycles.set("-");
text_ttef.set("-");
text_method.set("-");
text_warn.set("");
}

BattinfoView::BattinfoView(NavigationView& nav)
: nav_{nav} {
add_children({&labels,
Expand Down
5 changes: 5 additions & 0 deletions firmware/application/apps/ui_battinfo.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "string_format.hpp"
#include "i2cdevmanager.hpp"
#include "i2cdev_max17055.hpp"
#include "i2cdev_ads1110.hpp"

namespace ui {
class BattinfoView : public View {
Expand All @@ -43,6 +46,8 @@ class BattinfoView : public View {

private:
void update_result();
void update_results_max17055(i2cdev::I2cDev_MAX17055* dev);
void update_results_ads1110(i2cdev::I2cDev_ADS1110* dev);
void on_timer();
NavigationView& nav_;
uint16_t timer_period = 60;
Expand Down
20 changes: 12 additions & 8 deletions firmware/application/apps/ui_debug.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
#include "ui_font_fixed_8x16.hpp"
#include "ui_painter.hpp"
#include "ui_external_items_menu_loader.hpp"
#include "ui_debug_battery.hpp"
#include "ui_debug_max17055.hpp"

#include "portapack.hpp"
#include "portapack_persistent_memory.hpp"
Expand Down Expand Up @@ -226,8 +226,10 @@ uint32_t RegistersWidget::reg_read(const uint32_t register_number) {
return radio::debug::second_if::register_read(register_number);
case CT_SI5351:
return portapack::clock_generator.read_register(register_number);
case CT_BATTERY:
return battery::BatteryManagement::read_register(register_number);
case CT_MAX17055: {
i2cdev::I2cDev_MAX17055* dev = (i2cdev::I2cDev_MAX17055*)i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055);
return dev->read_register(register_number);
}
case CT_AUDIO:
return audio::debug::reg_read(register_number);
}
Expand All @@ -249,9 +251,11 @@ void RegistersWidget::reg_write(const uint32_t register_number, const uint32_t v
case CT_SI5351:
portapack::clock_generator.write_register(register_number, value);
break;
case CT_BATTERY:
battery::BatteryManagement::write_register(register_number, value);
case CT_MAX17055: {
i2cdev::I2cDev_MAX17055* dev = (i2cdev::I2cDev_MAX17055*)i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055);
dev->write_register(register_number, value);
break;
}
case CT_AUDIO:
audio::debug::reg_write(register_number, value);
break;
Expand Down Expand Up @@ -465,9 +469,9 @@ void DebugPeripheralsMenuView::on_populate() {
{si5351x, Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this, si5351x]() { nav_.push<RegistersView>(si5351x, RegistersWidgetConfig{CT_SI5351, 188, 96, 8}); }},
{audio::debug::codec_name(), Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>(audio::debug::codec_name(), RegistersWidgetConfig{CT_AUDIO, audio::debug::reg_count(), audio::debug::reg_count(), audio::debug::reg_bits()}); }},
});
if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BatteryModules::BATT_MAX17055) {
if (i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055)) {
add_item(
{"MAX17055", Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>("MAX17055", RegistersWidgetConfig{CT_BATTERY, 256, 16, 16}); }});
{"MAX17055", Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_peripherals_details, [this]() { nav_.push<RegistersView>("MAX17055", RegistersWidgetConfig{CT_MAX17055, 256, 16, 16}); }});
}
set_max_rows(2); // allow wider buttons
}
Expand Down Expand Up @@ -512,7 +516,7 @@ void DebugMenuView::on_populate() {
{"Reboot", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_setup, [this]() { nav_.push<DebugReboot>(); }},
});

if (battery::BatteryManagement::detectedModule() == battery::BatteryManagement::BatteryModules::BATT_MAX17055) {
if (i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055)) {
add_item(
{"Battery", ui::Theme::getInstance()->fg_darkcyan->foreground, &bitmap_icon_batt_icon, [this]() { nav_.push<BatteryCapacityView>(); }});
}
Expand Down
2 changes: 1 addition & 1 deletion firmware/application/apps/ui_debug.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ typedef enum {
CT_MAX283X,
CT_SI5351,
CT_AUDIO,
CT_BATTERY,
CT_MAX17055,
} chip_type_t;

struct RegistersWidgetConfig {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#include "ui_debug_battery.hpp"
#include "ui_debug_max17055.hpp"
#include "string_format.hpp"

namespace ui {

BatteryCapacityView::RegisterEntry BatteryCapacityView::get_entry(size_t index) {
if (index < battery::max17055::MAX17055::entries_count) {
return battery::max17055::MAX17055::entries[index];
if (index < i2cdev::I2cDev_MAX17055::entries_count) {
return i2cdev::I2cDev_MAX17055::entries[index];
}
return {"", 0, "", 0, false, "", false, 0, false, false, false, 0, false};
}
Expand All @@ -27,6 +27,12 @@ BatteryCapacityView::BatteryCapacityView(NavigationView& nav) {

button_done.on_select = [&nav](Button&) { nav.pop(); };

auto dev = (i2cdev::I2cDev_MAX17055*)i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055);
if (!dev) { // dev not found
nav.pop();
return;
}

populate_page(0);
update_page_text();
}
Expand All @@ -37,7 +43,7 @@ void BatteryCapacityView::focus() {

bool BatteryCapacityView::on_encoder(const EncoderEvent delta) {
int32_t new_page = current_page + delta;
if (new_page >= 0 && new_page < ((int32_t)battery::max17055::MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE) {
if (new_page >= 0 && new_page < ((int32_t)i2cdev::I2cDev_MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE) {
current_page = new_page;
populate_page(current_page * ENTRIES_PER_PAGE);
update_page_text();
Expand All @@ -46,11 +52,12 @@ bool BatteryCapacityView::on_encoder(const EncoderEvent delta) {
}

void BatteryCapacityView::update_values() {
i2cdev::I2cDev_MAX17055* dev = (i2cdev::I2cDev_MAX17055*)i2cdev::I2CDevManager::get_dev_by_model(I2C_DEVMDL::I2CDEVMDL_MAX17055);
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
size_t entry_index = current_page * ENTRIES_PER_PAGE + i;
if (entry_index < battery::max17055::MAX17055::entries_count) {
if (entry_index < i2cdev::I2cDev_MAX17055::entries_count) {
const auto entry = get_entry(entry_index);
uint16_t raw_value = battery::BatteryManagement::read_register(entry.address);
uint16_t raw_value = dev->read_register(entry.address);

hex_texts[i].set("0x" + to_string_hex(raw_value, 4));

Expand Down Expand Up @@ -78,7 +85,7 @@ void BatteryCapacityView::update_values() {
void BatteryCapacityView::populate_page(int start_index) {
for (size_t i = 0; i < ENTRIES_PER_PAGE; ++i) {
size_t entry_index = start_index + i;
if (entry_index < battery::max17055::MAX17055::entries_count) {
if (entry_index < i2cdev::I2cDev_MAX17055::entries_count) {
const auto entry = get_entry(entry_index);
name_texts[i].set(entry.name);
addr_texts[i].set("0x" + to_string_hex(entry.address, 2));
Expand All @@ -97,7 +104,7 @@ void BatteryCapacityView::populate_page(int start_index) {
}

void BatteryCapacityView::update_page_text() {
int total_pages = (battery::max17055::MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
int total_pages = (i2cdev::I2cDev_MAX17055::entries_count + ENTRIES_PER_PAGE - 1) / ENTRIES_PER_PAGE;
page_text.set("Page " + to_string_dec_uint(current_page + 1) + "/" + to_string_dec_uint(total_pages));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,20 @@
#include "ui_widget.hpp"
#include "ui_navigation.hpp"
#include "battery.hpp"
#include "max17055.hpp"
#include "i2cdevmanager.hpp"
#include "i2cdev_max17055.hpp"

namespace ui {

class BatteryCapacityView : public View {
public:
BatteryCapacityView(NavigationView& nav);
void focus() override;
std::string title() const override { return "Battery Registers"; }
std::string title() const override { return "MAX17055 Registers"; }

bool on_encoder(const EncoderEvent delta) override;

using RegisterEntry = battery::max17055::RegisterEntry;
using RegisterEntry = i2cdev::I2cDev_MAX17055::RegisterEntry;

private:
static RegisterEntry get_entry(size_t index);
Expand Down
Loading

0 comments on commit 83b65ba

Please sign in to comment.