mirror of
https://github.com/portapack-mayhem/mayhem-firmware.git
synced 2025-08-14 08:07:37 +00:00
support for battery if any + TPMS app to ext (#2129)
* batt initial * batt widgets * settings modify * batt info screen * ability to hide icon * battView * redo tmps * hide curr + charge if no data * fix flashing
This commit is contained in:
@@ -24,10 +24,11 @@
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
|
||||
namespace battery {
|
||||
namespace ads1110 {
|
||||
|
||||
constexpr float BATTERY_MIN_VOLTAGE = 3.0;
|
||||
constexpr float BATTERY_MAX_VOLTAGE = 4.0;
|
||||
constexpr uint16_t BATTERY_MIN_VOLTAGE = 3000;
|
||||
constexpr uint16_t BATTERY_MAX_VOLTAGE = 4000;
|
||||
|
||||
void ADS1110::init() {
|
||||
if (!detected_) {
|
||||
@@ -50,6 +51,7 @@ bool ADS1110::detect() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
detected_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -57,7 +59,8 @@ bool ADS1110::write(const uint8_t value) {
|
||||
return bus.transmit(bus_address, &value, 1);
|
||||
}
|
||||
|
||||
float ADS1110::readVoltage() {
|
||||
// returns the batt voltage in mV
|
||||
uint16_t ADS1110::readVoltage() {
|
||||
// Read the conversion result
|
||||
uint8_t data[3];
|
||||
if (!bus.receive(bus_address, data, 3)) {
|
||||
@@ -67,7 +70,7 @@ float ADS1110::readVoltage() {
|
||||
uint16_t raw = (static_cast<uint16_t>(data[0]) << 8) | data[1];
|
||||
|
||||
// Calculate the voltage based on the output code
|
||||
float voltage = 0.0f;
|
||||
int16_t voltage = 0;
|
||||
float minCode = 0;
|
||||
float pga = 0.0f;
|
||||
|
||||
@@ -110,21 +113,21 @@ float ADS1110::readVoltage() {
|
||||
}
|
||||
|
||||
// 2.048 is the reference voltage & 2.0 is to make up for the voltage divider
|
||||
voltage = raw / (-1.0 * minCode) * pga * 2.048 * 2.0;
|
||||
|
||||
return voltage;
|
||||
voltage = (int16_t)(raw / (-1.0 * minCode) * pga * 2.048 * 2.0 * 1000.0); // v to mV
|
||||
if (voltage < 0) voltage *= -1; // should not happen in this build, but prevent it
|
||||
return (uint16_t)voltage;
|
||||
}
|
||||
|
||||
void ADS1110::getBatteryInfo(float& batteryPercentage, float& voltage) {
|
||||
void ADS1110::getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage) {
|
||||
voltage = readVoltage();
|
||||
|
||||
// Calculate the remaining battery percentage
|
||||
batteryPercentage = (voltage - BATTERY_MIN_VOLTAGE) /
|
||||
(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0;
|
||||
batteryPercentage = (float)(voltage - BATTERY_MIN_VOLTAGE) / (float)(BATTERY_MAX_VOLTAGE - BATTERY_MIN_VOLTAGE) * 100.0;
|
||||
|
||||
// Limit the values to the valid range
|
||||
batteryPercentage = std::clamp(batteryPercentage, 0.0f, 100.0f);
|
||||
batteryPercentage = (batteryPercentage > 100) ? 100 : batteryPercentage;
|
||||
// ToDo: if its > 4, then 100%, if < 3 then 0%
|
||||
}
|
||||
|
||||
} /* namespace ads1110 */
|
||||
} // namespace battery
|
@@ -27,11 +27,10 @@
|
||||
#include <string>
|
||||
|
||||
#include "i2c_pp.hpp"
|
||||
|
||||
namespace battery {
|
||||
namespace ads1110 {
|
||||
|
||||
using address_t = uint8_t;
|
||||
using reg_t = uint16_t;
|
||||
|
||||
class ADS1110 {
|
||||
public:
|
||||
@@ -39,10 +38,11 @@ class ADS1110 {
|
||||
: bus(bus), bus_address(bus_address), detected_(false) {}
|
||||
|
||||
void init();
|
||||
bool detect();
|
||||
bool isDetected() const { return detected_; }
|
||||
|
||||
float readVoltage();
|
||||
void getBatteryInfo(float& batteryPercentage, float& voltage);
|
||||
uint16_t readVoltage();
|
||||
void getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage);
|
||||
|
||||
private:
|
||||
I2C& bus;
|
||||
@@ -50,9 +50,8 @@ class ADS1110 {
|
||||
bool detected_;
|
||||
|
||||
bool write(const uint8_t value);
|
||||
bool detect();
|
||||
};
|
||||
|
||||
} /* namespace ads1110 */
|
||||
|
||||
} // namespace battery
|
||||
#endif /* __ADS1110_H__ */
|
111
firmware/common/battery.cpp
Normal file
111
firmware/common/battery.cpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#include "battery.hpp"
|
||||
#include "event_m0.hpp"
|
||||
#include "portapack.hpp"
|
||||
#include "ads1110.hpp"
|
||||
|
||||
// uncomment if you want to emulate batt management system
|
||||
// #define USE_BATT_EMULATOR
|
||||
|
||||
extern I2C portapack::i2c0;
|
||||
|
||||
namespace battery {
|
||||
|
||||
constexpr uint32_t BATTERY_UPDATE_INTERVAL = 30000;
|
||||
BatteryManagement::BatteryModules BatteryManagement::detected_ = BatteryManagement::BATT_NONE;
|
||||
|
||||
ads1110::ADS1110 battery_ads1110{portapack::i2c0, 0x48};
|
||||
|
||||
Thread* BatteryManagement::thread = nullptr;
|
||||
|
||||
void BatteryManagement::init() {
|
||||
// try to detect supported modules
|
||||
detected_ = BATT_NONE;
|
||||
if (battery_ads1110.detect()) {
|
||||
battery_ads1110.init();
|
||||
detected_ = BATT_ADS1110;
|
||||
}
|
||||
|
||||
// add new supported module detect + init here
|
||||
|
||||
#ifdef USE_BATT_EMULATOR
|
||||
if (detected_ == BATT_NONE) {
|
||||
detected_ = BATT_EMULATOR;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (detected_ != BATT_NONE) {
|
||||
// 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, bool& isCharging) {
|
||||
if (detected_ == BATT_NONE) return false;
|
||||
if (detected_ == BATT_ADS1110) {
|
||||
battery_ads1110.getBatteryInfo(batteryPercentage, voltage);
|
||||
return true;
|
||||
}
|
||||
// add new module query here
|
||||
|
||||
#ifdef USE_BATT_EMULATOR
|
||||
if (detected_ == BATT_EMULATOR) {
|
||||
batteryPercentage += 5; // %
|
||||
if (batteryPercentage > 100) batteryPercentage = 0;
|
||||
voltage = rand() % 1000 + 3000; // mV
|
||||
current = rand() % 150; // mA
|
||||
isCharging = rand() % 2;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
(void)isCharging; // keep the compiler calm
|
||||
(void)current;
|
||||
return false;
|
||||
}
|
||||
|
||||
uint8_t BatteryManagement::getPercent() {
|
||||
if (detected_ == BATT_NONE) return 102;
|
||||
uint8_t batteryPercentage = 0;
|
||||
bool isCharging = false;
|
||||
uint16_t voltage = 0;
|
||||
int32_t current = 0;
|
||||
getBatteryInfo(batteryPercentage, voltage, current, isCharging);
|
||||
return batteryPercentage;
|
||||
}
|
||||
|
||||
uint16_t BatteryManagement::getVoltage() {
|
||||
if (detected_ == BATT_NONE) return 0;
|
||||
if (detected_ == BATT_NONE) return 102;
|
||||
uint8_t batteryPercentage = 0;
|
||||
bool isCharging = false;
|
||||
uint16_t voltage = 0;
|
||||
int32_t current = 0;
|
||||
getBatteryInfo(batteryPercentage, voltage, current, isCharging);
|
||||
return voltage;
|
||||
}
|
||||
|
||||
msg_t BatteryManagement::timer_fn(void* arg) {
|
||||
(void)arg;
|
||||
if (!detected_) return 0;
|
||||
uint8_t batteryPercentage = 102;
|
||||
bool isCharging = false;
|
||||
uint16_t voltage = 0;
|
||||
int32_t current = 0;
|
||||
chThdSleepMilliseconds(1000); // wait ui for fully load
|
||||
while (1) {
|
||||
if (BatteryManagement::getBatteryInfo(batteryPercentage, voltage, current, isCharging)) {
|
||||
// send local message
|
||||
BatteryStateMessage msg{batteryPercentage, isCharging, voltage};
|
||||
EventDispatcher::send_message(msg);
|
||||
}
|
||||
chThdSleepMilliseconds(BATTERY_UPDATE_INTERVAL);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void BatteryManagement::create_thread() {
|
||||
thread = chThdCreateFromHeap(NULL, 512, NORMALPRIO, BatteryManagement::timer_fn, nullptr);
|
||||
}
|
||||
|
||||
} // namespace battery
|
50
firmware/common/battery.hpp
Normal file
50
firmware/common/battery.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (C) 2024 HTotoo.
|
||||
*
|
||||
* This file is part of PortaPack.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; see the file COPYING. If not, write to
|
||||
* the Free Software Foundation, Inc., 51 Franklin Street,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#ifndef __BATTERY_H__
|
||||
#define __BATTERY_H__
|
||||
|
||||
#include <cstdint>
|
||||
#include "ch.h"
|
||||
|
||||
namespace battery {
|
||||
|
||||
class BatteryManagement {
|
||||
public:
|
||||
enum BatteryModules {
|
||||
BATT_NONE = 0,
|
||||
BATT_ADS1110 = 1,
|
||||
BATT_EMULATOR = 254
|
||||
};
|
||||
static void init();
|
||||
static bool isDetected() { return detected_ != BATT_NONE; }
|
||||
static bool getBatteryInfo(uint8_t& batteryPercentage, uint16_t& voltage, int32_t& current, bool& isCharging);
|
||||
static uint16_t getVoltage();
|
||||
static uint8_t getPercent();
|
||||
|
||||
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
|
||||
};
|
||||
}; // namespace battery
|
||||
#endif
|
@@ -123,6 +123,7 @@ class Message {
|
||||
EnvironmentData = 65,
|
||||
AudioBeep = 66,
|
||||
PocsagTosend = 67,
|
||||
BatteryStateData = 68,
|
||||
MAX
|
||||
};
|
||||
|
||||
@@ -1409,4 +1410,20 @@ class PocsagTosendMessage : public Message {
|
||||
uint64_t addr = 0;
|
||||
};
|
||||
|
||||
class BatteryStateMessage : public Message {
|
||||
public:
|
||||
constexpr BatteryStateMessage(
|
||||
uint8_t percent,
|
||||
bool on_charger,
|
||||
uint16_t voltage)
|
||||
: Message{ID::BatteryStateData},
|
||||
percent{percent},
|
||||
on_charger{on_charger},
|
||||
voltage{voltage} {
|
||||
}
|
||||
uint8_t percent = 0;
|
||||
bool on_charger = false;
|
||||
uint16_t voltage = 0; // mV
|
||||
};
|
||||
|
||||
#endif /*__MESSAGE_H__*/
|
||||
|
@@ -132,8 +132,8 @@ struct ui_config2_t {
|
||||
|
||||
bool hide_mute : 1;
|
||||
bool hide_fake_brightness : 1;
|
||||
bool UNUSED_1 : 1;
|
||||
bool UNUSED_2 : 1;
|
||||
bool hide_numeric_battery : 1;
|
||||
bool hide_battery_icon : 1;
|
||||
bool UNUSED_3 : 1;
|
||||
bool UNUSED_4 : 1;
|
||||
bool UNUSED_5 : 1;
|
||||
@@ -423,6 +423,7 @@ void defaults() {
|
||||
set_encoder_dial_sensitivity(DIAL_SENSITIVITY_NORMAL);
|
||||
set_config_speaker_disable(true); // Disable AK4951 speaker by default (in case of OpenSourceSDRLab H2)
|
||||
set_menu_color(Color::grey());
|
||||
set_ui_hide_numeric_battery(true); // hide the numeric battery by default - no space to display it
|
||||
|
||||
// Default values for recon app.
|
||||
set_recon_autosave_freqs(false);
|
||||
@@ -954,6 +955,13 @@ bool ui_hide_fake_brightness() {
|
||||
return data->ui_config2.hide_fake_brightness;
|
||||
}
|
||||
|
||||
bool ui_hide_numeric_battery() {
|
||||
return data->ui_config2.hide_numeric_battery;
|
||||
}
|
||||
bool ui_hide_battery_icon() {
|
||||
return data->ui_config2.hide_battery_icon;
|
||||
}
|
||||
|
||||
void set_ui_hide_speaker(bool v) {
|
||||
data->ui_config2.hide_speaker = v;
|
||||
}
|
||||
@@ -986,6 +994,12 @@ void set_ui_hide_sd_card(bool v) {
|
||||
void set_ui_hide_fake_brightness(bool v) {
|
||||
data->ui_config2.hide_fake_brightness = v;
|
||||
}
|
||||
void set_ui_hide_numeric_battery(bool v) {
|
||||
data->ui_config2.hide_numeric_battery = v;
|
||||
}
|
||||
void set_ui_hide_battery_icon(bool v) {
|
||||
data->ui_config2.hide_battery_icon = v;
|
||||
}
|
||||
|
||||
/* Converter */
|
||||
bool config_converter() {
|
||||
@@ -1248,6 +1262,8 @@ bool debug_dump() {
|
||||
pmem_dump_file.write_line("ui_config2 hide_sd_card: " + to_string_dec_uint(data->ui_config2.hide_sd_card));
|
||||
pmem_dump_file.write_line("ui_config2 hide_mute: " + to_string_dec_uint(data->ui_config2.hide_mute));
|
||||
pmem_dump_file.write_line("ui_config2 hide_fake_brightness: " + to_string_dec_uint(data->ui_config2.hide_fake_brightness));
|
||||
pmem_dump_file.write_line("ui_config2 hide_battery_icon: " + to_string_dec_uint(data->ui_config2.hide_battery_icon));
|
||||
pmem_dump_file.write_line("ui_config2 hide_numeric_battery: " + to_string_dec_uint(data->ui_config2.hide_numeric_battery));
|
||||
|
||||
// misc_config bits
|
||||
pmem_dump_file.write_line("misc_config config_audio_mute: " + to_string_dec_int(config_audio_mute()));
|
||||
|
@@ -335,6 +335,8 @@ bool ui_hide_sleep();
|
||||
bool ui_hide_bias_tee();
|
||||
bool ui_hide_clock();
|
||||
bool ui_hide_fake_brightness();
|
||||
bool ui_hide_numeric_battery();
|
||||
bool ui_hide_battery_icon();
|
||||
bool ui_hide_sd_card();
|
||||
void set_ui_hide_speaker(bool v);
|
||||
void set_ui_hide_mute(bool v);
|
||||
@@ -345,6 +347,8 @@ void set_ui_hide_sleep(bool v);
|
||||
void set_ui_hide_bias_tee(bool v);
|
||||
void set_ui_hide_clock(bool v);
|
||||
void set_ui_hide_fake_brightness(bool v);
|
||||
void set_ui_hide_numeric_battery(bool v);
|
||||
void set_ui_hide_battery_icon(bool v);
|
||||
void set_ui_hide_sd_card(bool v);
|
||||
|
||||
// sd persisting settings
|
||||
|
@@ -2044,6 +2044,135 @@ bool TextField::on_touch(TouchEvent event) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/* BatteryIcon *************************************************************/
|
||||
|
||||
BatteryIcon::BatteryIcon(Rect parent_rect, uint8_t percent)
|
||||
: Widget(parent_rect) {
|
||||
this->set_battery(percent, false);
|
||||
set_focusable(true);
|
||||
}
|
||||
|
||||
void BatteryIcon::getAccessibilityText(std::string& result) {
|
||||
result = to_string_dec_uint(percent_) + "%";
|
||||
}
|
||||
void BatteryIcon::getWidgetName(std::string& result) {
|
||||
result = "Battery percent";
|
||||
}
|
||||
|
||||
void BatteryIcon::set_battery(uint8_t percentage, bool charge) {
|
||||
if (charge == charge_ && percent_ == percentage) return;
|
||||
percent_ = percentage;
|
||||
charge_ = charge;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
bool BatteryIcon::on_key(KeyEvent key) {
|
||||
if (key == KeyEvent::Select && on_select) {
|
||||
on_select();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BatteryIcon::on_touch(TouchEvent event) {
|
||||
if (event.type == TouchEvent::Type::Start) {
|
||||
focus();
|
||||
return true;
|
||||
}
|
||||
if (event.type == TouchEvent::Type::End && on_select) {
|
||||
on_select();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void BatteryIcon::paint(Painter& painter) {
|
||||
ui::Rect rect = screen_rect(); // 10, 1 * 16
|
||||
painter.fill_rectangle(rect, has_focus() || highlighted() ? Color::light_grey() : Color::dark_grey()); // clear
|
||||
ui::Color battColor = (charge_) ? Color::cyan() : Color::green();
|
||||
// batt body:
|
||||
painter.draw_vline({rect.left() + 1, rect.top() + 2}, rect.height() - 4, battColor);
|
||||
painter.draw_vline({rect.right() - 2, rect.top() + 2}, rect.height() - 4, battColor);
|
||||
painter.draw_hline({rect.left() + 1, rect.top() + 2}, rect.width() - 2, battColor);
|
||||
painter.draw_hline({rect.left() + 1, rect.bottom() - 2}, rect.width() - 2, battColor);
|
||||
// batt cap:
|
||||
painter.draw_hline({rect.left() + 3, rect.top() + 1}, rect.width() - 6, battColor);
|
||||
painter.draw_hline({rect.left() + 3, 0}, rect.width() - 6, battColor);
|
||||
if (percent_ > 100) { // error / unk
|
||||
painter.draw_string({rect.left() + 2, rect.top() + 3}, font::fixed_5x8, Color::white(), Color::dark_grey(), "?");
|
||||
return;
|
||||
}
|
||||
int8_t ppx = (rect.bottom() - 3) - (rect.top() + 2); // 11px max height to draw bars
|
||||
int8_t ptd = (int8_t)((static_cast<float>(percent_) / 100.0f) * (float)ppx + 0.5); // pixels to draw
|
||||
int8_t pp = ppx - ptd; // pixels to start from
|
||||
|
||||
if (percent_ >= 70)
|
||||
battColor = Color::green();
|
||||
else if (percent_ >= 40)
|
||||
battColor = Color::orange();
|
||||
else
|
||||
battColor = Color::red();
|
||||
// fill the bars
|
||||
for (int y = pp; y < ppx; y++) {
|
||||
painter.draw_hline({rect.left() + 2, rect.top() + 3 + y}, rect.width() - 4, battColor);
|
||||
}
|
||||
}
|
||||
|
||||
/* BatteryTextField *************************************************************/
|
||||
|
||||
BatteryTextField::BatteryTextField(Rect parent_rect, uint8_t percent)
|
||||
: Widget(parent_rect) {
|
||||
this->set_battery(percent, false);
|
||||
set_focusable(true);
|
||||
}
|
||||
|
||||
void BatteryTextField::paint(Painter& painter) {
|
||||
Color bg = has_focus() || highlighted() ? Color::light_grey() : Color::dark_grey();
|
||||
ui::Rect rect = screen_rect(); // 2 * 8, 1 * 16
|
||||
painter.fill_rectangle(rect, bg); // clear
|
||||
std::string txt_batt = percent_ <= 100 ? to_string_dec_uint(percent_) : "UNK";
|
||||
int xdelta = 0;
|
||||
if (txt_batt.length() == 1)
|
||||
xdelta = 5;
|
||||
else if (txt_batt.length() == 2)
|
||||
xdelta = 2;
|
||||
painter.draw_string({rect.left() + xdelta, rect.top()}, font::fixed_5x8, Color::white(), bg, txt_batt);
|
||||
painter.draw_string({rect.left(), rect.top() + 8}, font::fixed_5x8, Color::white(), bg, (charge_) ? "+%" : " %");
|
||||
}
|
||||
|
||||
void BatteryTextField::getAccessibilityText(std::string& result) {
|
||||
result = to_string_dec_uint(percent_) + "%";
|
||||
}
|
||||
void BatteryTextField::getWidgetName(std::string& result) {
|
||||
result = "Battery percent";
|
||||
}
|
||||
|
||||
void BatteryTextField::set_battery(uint8_t percentage, bool charge) {
|
||||
if (charge == charge_ && percent_ == percentage) return;
|
||||
charge_ = charge;
|
||||
percent_ = percentage;
|
||||
set_dirty();
|
||||
}
|
||||
|
||||
bool BatteryTextField::on_key(KeyEvent key) {
|
||||
if (key == KeyEvent::Select && on_select) {
|
||||
on_select();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool BatteryTextField::on_touch(TouchEvent event) {
|
||||
if (event.type == TouchEvent::Type::Start) {
|
||||
focus();
|
||||
return true;
|
||||
}
|
||||
if (event.type == TouchEvent::Type::End && on_select) {
|
||||
on_select();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* NumberField ***********************************************************/
|
||||
|
||||
NumberField::NumberField(
|
||||
|
@@ -33,6 +33,8 @@
|
||||
#include "portapack.hpp"
|
||||
#include "utility.hpp"
|
||||
|
||||
#include "ui/ui_font_fixed_5x8.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
@@ -781,6 +783,52 @@ class TextField : public Text {
|
||||
using Text::set;
|
||||
};
|
||||
|
||||
class BatteryTextField : public Widget {
|
||||
public:
|
||||
std::function<void()> on_select{};
|
||||
|
||||
BatteryTextField(Rect parent_rect, uint8_t percent);
|
||||
void paint(Painter& painter) override;
|
||||
|
||||
void set_battery(uint8_t percentage, bool charge);
|
||||
void set_text(std::string_view value);
|
||||
|
||||
bool on_key(KeyEvent key) override;
|
||||
bool on_touch(TouchEvent event) override;
|
||||
|
||||
void getAccessibilityText(std::string& result) override;
|
||||
void getWidgetName(std::string& result) override;
|
||||
|
||||
private:
|
||||
uint8_t percent_{102};
|
||||
bool charge_{false};
|
||||
|
||||
static constexpr Style style{
|
||||
.font = font::fixed_5x8,
|
||||
.background = Color::dark_grey(),
|
||||
.foreground = Color::white(),
|
||||
};
|
||||
};
|
||||
|
||||
class BatteryIcon : public Widget {
|
||||
public:
|
||||
std::function<void()> on_select{};
|
||||
|
||||
BatteryIcon(Rect parent_rect, uint8_t percent);
|
||||
void paint(Painter& painter) override;
|
||||
void set_battery(uint8_t percentage, bool charge);
|
||||
|
||||
bool on_key(KeyEvent key) override;
|
||||
bool on_touch(TouchEvent event) override;
|
||||
|
||||
void getAccessibilityText(std::string& result) override;
|
||||
void getWidgetName(std::string& result) override;
|
||||
|
||||
private:
|
||||
uint8_t percent_{102};
|
||||
bool charge_{false};
|
||||
};
|
||||
|
||||
class NumberField : public Widget {
|
||||
public:
|
||||
std::function<void(NumberField&)> on_select{};
|
||||
|
Reference in New Issue
Block a user