Move battery measurement to its own class
This commit is contained in:
@@ -0,0 +1,10 @@
|
||||
# Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
#
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
idf_component_register(
|
||||
SRCS "battery.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "drivers" "events")
|
||||
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#include "battery.hpp"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "adc.hpp"
|
||||
#include "event_queue.hpp"
|
||||
#include "freertos/portmacro.h"
|
||||
#include "samd.hpp"
|
||||
#include "system_events.hpp"
|
||||
|
||||
namespace battery {
|
||||
|
||||
static const TickType_t kBatteryCheckPeriod = pdMS_TO_TICKS(60 * 1000);
|
||||
|
||||
/*
|
||||
* Battery voltage, in millivolts, at which the battery charger IC will stop
|
||||
* charging.
|
||||
*/
|
||||
static const uint32_t kFullChargeMilliVolts = 4200;
|
||||
|
||||
/*
|
||||
* Battery voltage, in millivolts, at which *we* will consider the battery to
|
||||
* be completely discharged. This is intentionally higher than the charger IC
|
||||
* cut-off and the protection on the battery itself; we want to make sure we
|
||||
* finish up and have everything unmounted and snoozing before the BMS cuts us
|
||||
* off.
|
||||
*/
|
||||
static const uint32_t kEmptyChargeMilliVolts = 3200; // BMS limit is 3100.
|
||||
|
||||
using ChargeStatus = drivers::Samd::ChargeStatus;
|
||||
|
||||
void check_voltage_cb(TimerHandle_t timer) {
|
||||
Battery* instance = reinterpret_cast<Battery*>(pvTimerGetTimerID(timer));
|
||||
instance->Update();
|
||||
}
|
||||
|
||||
Battery::Battery(drivers::Samd* samd, drivers::AdcBattery* adc)
|
||||
: samd_(samd), adc_(adc) {
|
||||
timer_ = xTimerCreate("BATTERY", kBatteryCheckPeriod, true, this,
|
||||
check_voltage_cb);
|
||||
xTimerStart(timer_, portMAX_DELAY);
|
||||
Update();
|
||||
}
|
||||
|
||||
Battery::~Battery() {
|
||||
xTimerStop(timer_, portMAX_DELAY);
|
||||
xTimerDelete(timer_, portMAX_DELAY);
|
||||
}
|
||||
|
||||
auto Battery::Update() -> void {
|
||||
std::lock_guard<std::mutex> lock{state_mutex_};
|
||||
|
||||
auto charge_state = samd_->GetChargeStatus();
|
||||
if (!charge_state || *charge_state == ChargeStatus::kNoBattery) {
|
||||
if (state_) {
|
||||
EmitEvent();
|
||||
}
|
||||
state_.reset();
|
||||
return;
|
||||
}
|
||||
// FIXME: So what we *should* do here is measure the actual real-life
|
||||
// time from full battery -> empty battery, store it in NVS, then rely on
|
||||
// that. If someone could please do this, it would be lovely. Thanks!
|
||||
uint32_t mV = std::max(adc_->Millivolts(), kEmptyChargeMilliVolts);
|
||||
uint_fast8_t percent = static_cast<uint_fast8_t>(std::min<double>(
|
||||
std::max<double>(0.0, mV - kEmptyChargeMilliVolts) /
|
||||
(kFullChargeMilliVolts - kEmptyChargeMilliVolts) * 100.0,
|
||||
100.0));
|
||||
|
||||
bool is_charging = *charge_state == ChargeStatus::kChargingRegular ||
|
||||
*charge_state == ChargeStatus::kChargingFast ||
|
||||
*charge_state == ChargeStatus::kFullCharge;
|
||||
|
||||
if (!state_ || state_->is_charging != is_charging ||
|
||||
state_->percent != percent) {
|
||||
EmitEvent();
|
||||
}
|
||||
|
||||
state_ = BatteryState{
|
||||
.percent = percent,
|
||||
.is_charging = is_charging,
|
||||
};
|
||||
}
|
||||
|
||||
auto Battery::State() -> std::optional<BatteryState> {
|
||||
std::lock_guard<std::mutex> lock{state_mutex_};
|
||||
return state_;
|
||||
}
|
||||
|
||||
auto Battery::EmitEvent() -> void {
|
||||
events::System().Dispatch(system_fsm::BatteryStateChanged{});
|
||||
events::Ui().Dispatch(system_fsm::BatteryStateChanged{});
|
||||
}
|
||||
|
||||
} // namespace battery
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2023 jacqueline <me@jacqueline.id.au>
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/timers.h"
|
||||
|
||||
#include "adc.hpp"
|
||||
#include "samd.hpp"
|
||||
|
||||
namespace battery {
|
||||
|
||||
class Battery {
|
||||
public:
|
||||
Battery(drivers::Samd* samd, drivers::AdcBattery* adc);
|
||||
~Battery();
|
||||
|
||||
auto Update() -> void;
|
||||
|
||||
struct BatteryState {
|
||||
uint_fast8_t percent;
|
||||
bool is_charging;
|
||||
};
|
||||
|
||||
auto State() -> std::optional<BatteryState>;
|
||||
|
||||
private:
|
||||
auto EmitEvent() -> void;
|
||||
|
||||
drivers::Samd* samd_;
|
||||
drivers::AdcBattery* adc_;
|
||||
|
||||
TimerHandle_t timer_;
|
||||
std::mutex state_mutex_;
|
||||
std::optional<BatteryState> state_;
|
||||
};
|
||||
|
||||
} // namespace battery
|
||||
@@ -3,7 +3,7 @@
|
||||
# SPDX-License-Identifier: GPL-3.0-only
|
||||
|
||||
idf_component_register(
|
||||
SRCS "touchwheel.cpp" "i2s_dac.cpp" "gpios.cpp" "battery.cpp" "storage.cpp" "i2c.cpp"
|
||||
SRCS "touchwheel.cpp" "i2s_dac.cpp" "gpios.cpp" "adc.cpp" "storage.cpp" "i2c.cpp"
|
||||
"spi.cpp" "display.cpp" "display_init.cpp" "samd.cpp" "relative_wheel.cpp" "wm8523.cpp"
|
||||
"nvs.cpp" "bluetooth.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* SPDX-License-Identifier: GPL-3.0-only
|
||||
*/
|
||||
|
||||
#include "battery.hpp"
|
||||
#include "adc.hpp"
|
||||
#include <cstdint>
|
||||
|
||||
#include "esp_adc/adc_cali.h"
|
||||
@@ -14,21 +14,6 @@
|
||||
|
||||
namespace drivers {
|
||||
|
||||
/*
|
||||
* Battery voltage, in millivolts, at which the battery charger IC will stop
|
||||
* charging.
|
||||
*/
|
||||
static const uint32_t kFullChargeMilliVolts = 4200;
|
||||
|
||||
/*
|
||||
* Battery voltage, in millivolts, at which *we* will consider the battery to
|
||||
* be completely discharged. This is intentionally higher than the charger IC
|
||||
* cut-off and the protection on the battery itself; we want to make sure we
|
||||
* finish up and have everything unmounted and snoozing before the BMS cuts us
|
||||
* off.
|
||||
*/
|
||||
static const uint32_t kEmptyChargeMilliVolts = 3200; // BMS limit is 3100.
|
||||
|
||||
static const adc_bitwidth_t kAdcBitWidth = ADC_BITWIDTH_12;
|
||||
static const adc_unit_t kAdcUnit = ADC_UNIT_1;
|
||||
// Max battery voltage should be a little over 2V due to our divider, so we need
|
||||
@@ -37,7 +22,7 @@ static const adc_atten_t kAdcAttenuation = ADC_ATTEN_DB_11;
|
||||
// Corresponds to SENSOR_VP.
|
||||
static const adc_channel_t kAdcChannel = ADC_CHANNEL_0;
|
||||
|
||||
Battery::Battery() {
|
||||
AdcBattery::AdcBattery() {
|
||||
adc_oneshot_unit_init_cfg_t unit_config = {
|
||||
.unit_id = kAdcUnit,
|
||||
};
|
||||
@@ -59,16 +44,14 @@ Battery::Battery() {
|
||||
};
|
||||
ESP_ERROR_CHECK(adc_cali_create_scheme_line_fitting(
|
||||
&calibration_config, &adc_calibration_handle_));
|
||||
|
||||
UpdatePercent();
|
||||
}
|
||||
|
||||
Battery::~Battery() {
|
||||
AdcBattery::~AdcBattery() {
|
||||
adc_cali_delete_scheme_line_fitting(adc_calibration_handle_);
|
||||
ESP_ERROR_CHECK(adc_oneshot_del_unit(adc_handle_));
|
||||
}
|
||||
|
||||
auto Battery::Millivolts() -> uint32_t {
|
||||
auto AdcBattery::Millivolts() -> uint32_t {
|
||||
// GPIO 34
|
||||
int raw = 0;
|
||||
ESP_ERROR_CHECK(adc_oneshot_read(adc_handle_, kAdcChannel, &raw));
|
||||
@@ -81,17 +64,4 @@ auto Battery::Millivolts() -> uint32_t {
|
||||
return voltage * 2;
|
||||
}
|
||||
|
||||
auto Battery::UpdatePercent() -> bool {
|
||||
auto old_percent = percent_;
|
||||
// FIXME: So what we *should* do here is measure the actual real-life
|
||||
// time from full battery -> empty battery, store it in NVS, then rely on
|
||||
// that. If someone could please do this, it would be lovely. Thanks!
|
||||
uint32_t mV = std::max(Millivolts(), kEmptyChargeMilliVolts);
|
||||
percent_ = static_cast<uint_fast8_t>(std::min<double>(
|
||||
std::max<double>(0.0, mV - kEmptyChargeMilliVolts) /
|
||||
(kFullChargeMilliVolts - kEmptyChargeMilliVolts) * 100.0,
|
||||
100.0));
|
||||
return old_percent != percent_;
|
||||
}
|
||||
|
||||
} // namespace drivers
|
||||
@@ -15,25 +15,23 @@
|
||||
|
||||
namespace drivers {
|
||||
|
||||
class Battery {
|
||||
/*
|
||||
* Handles measuring the battery's current voltage.
|
||||
*/
|
||||
class AdcBattery {
|
||||
public:
|
||||
static auto Create() -> Battery* { return new Battery(); }
|
||||
Battery();
|
||||
~Battery();
|
||||
static auto Create() -> AdcBattery* { return new AdcBattery(); }
|
||||
AdcBattery();
|
||||
~AdcBattery();
|
||||
|
||||
/**
|
||||
* Returns the current battery level in millivolts.
|
||||
*/
|
||||
auto Millivolts() -> uint32_t;
|
||||
|
||||
auto UpdatePercent() -> bool;
|
||||
auto Percent() -> uint_fast8_t { return percent_; }
|
||||
|
||||
private:
|
||||
adc_oneshot_unit_handle_t adc_handle_;
|
||||
adc_cali_handle_t adc_calibration_handle_;
|
||||
|
||||
uint_fast8_t percent_;
|
||||
};
|
||||
|
||||
} // namespace drivers
|
||||
@@ -5,5 +5,5 @@
|
||||
idf_component_register(
|
||||
SRCS "system_fsm.cpp" "running.cpp" "booting.cpp" "idle.cpp"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "tinyfsm" "drivers" "database" "ui" "result" "events" "audio" "app_console")
|
||||
REQUIRES "tinyfsm" "drivers" "database" "ui" "result" "events" "audio" "app_console" "battery")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
|
||||
|
||||
@@ -38,12 +38,6 @@ namespace states {
|
||||
|
||||
static const char kTag[] = "BOOT";
|
||||
|
||||
static const TickType_t kBatteryCheckPeriod = pdMS_TO_TICKS(60 * 1000);
|
||||
|
||||
static void battery_timer_cb(TimerHandle_t timer) {
|
||||
events::System().Dispatch(internal::BatteryTimerFired{});
|
||||
}
|
||||
|
||||
auto Booting::entry() -> void {
|
||||
ESP_LOGI(kTag, "beginning tangara boot");
|
||||
ESP_LOGI(kTag, "installing early drivers");
|
||||
@@ -53,33 +47,31 @@ auto Booting::entry() -> void {
|
||||
ESP_ERROR_CHECK(drivers::init_spi());
|
||||
sGpios.reset(drivers::Gpios::Create());
|
||||
|
||||
sSamd.reset(drivers::Samd::Create());
|
||||
sAdc.reset(drivers::AdcBattery::Create());
|
||||
assert(sSamd.get() && sAdc.get());
|
||||
|
||||
sBattery.reset(new battery::Battery(sSamd.get(), sAdc.get()));
|
||||
|
||||
// Start bringing up LVGL now, since we have all of its prerequisites.
|
||||
sTrackQueue.reset(new audio::TrackQueue());
|
||||
ESP_LOGI(kTag, "starting ui");
|
||||
if (!ui::UiState::Init(sGpios.get(), sTrackQueue.get())) {
|
||||
if (!ui::UiState::Init(sGpios.get(), sTrackQueue.get(), sBattery)) {
|
||||
events::System().Dispatch(FatalError{});
|
||||
return;
|
||||
}
|
||||
|
||||
// Install everything else that is certain to be needed.
|
||||
ESP_LOGI(kTag, "installing remaining drivers");
|
||||
sSamd.reset(drivers::Samd::Create());
|
||||
sBattery.reset(drivers::Battery::Create());
|
||||
sNvs.reset(drivers::NvsStorage::Open());
|
||||
sTagParser.reset(new database::TagParserImpl());
|
||||
|
||||
if (!sSamd || !sBattery || !sNvs) {
|
||||
if (!sNvs) {
|
||||
events::System().Dispatch(FatalError{});
|
||||
events::Ui().Dispatch(FatalError{});
|
||||
return;
|
||||
}
|
||||
|
||||
ESP_LOGI(kTag, "battery is at %u%% (= %lu mV)", sBattery->Percent(),
|
||||
sBattery->Millivolts());
|
||||
TimerHandle_t battery_timer = xTimerCreate("battery", kBatteryCheckPeriod,
|
||||
true, NULL, battery_timer_cb);
|
||||
xTimerStart(battery_timer, portMAX_DELAY);
|
||||
|
||||
// ESP_LOGI(kTag, "starting bluetooth");
|
||||
// sBluetooth.reset(new drivers::Bluetooth(sNvs.get()));
|
||||
// sBluetooth->Enable();
|
||||
|
||||
@@ -53,7 +53,7 @@ struct HasPhonesChanged : tinyfsm::Event {
|
||||
};
|
||||
|
||||
struct ChargingStatusChanged : tinyfsm::Event {};
|
||||
struct BatteryPercentChanged : tinyfsm::Event {};
|
||||
struct BatteryStateChanged : tinyfsm::Event {};
|
||||
|
||||
namespace internal {
|
||||
|
||||
@@ -62,8 +62,6 @@ struct SamdInterrupt : tinyfsm::Event {};
|
||||
|
||||
struct IdleTimeout : tinyfsm::Event {};
|
||||
|
||||
struct BatteryTimerFired : tinyfsm::Event {};
|
||||
|
||||
} // namespace internal
|
||||
|
||||
} // namespace system_fsm
|
||||
|
||||
@@ -48,7 +48,6 @@ class SystemState : public tinyfsm::Fsm<SystemState> {
|
||||
void react(const FatalError&);
|
||||
void react(const internal::GpioInterrupt&);
|
||||
void react(const internal::SamdInterrupt&);
|
||||
void react(const internal::BatteryTimerFired&);
|
||||
|
||||
virtual void react(const DisplayReady&) {}
|
||||
virtual void react(const BootComplete&) {}
|
||||
@@ -67,7 +66,8 @@ class SystemState : public tinyfsm::Fsm<SystemState> {
|
||||
|
||||
static std::shared_ptr<drivers::TouchWheel> sTouch;
|
||||
static std::shared_ptr<drivers::RelativeWheel> sRelativeTouch;
|
||||
static std::shared_ptr<drivers::Battery> sBattery;
|
||||
static std::shared_ptr<drivers::AdcBattery> sAdc;
|
||||
static std::shared_ptr<battery::Battery> sBattery;
|
||||
static std::shared_ptr<drivers::SdStorage> sStorage;
|
||||
static std::shared_ptr<drivers::Display> sDisplay;
|
||||
static std::shared_ptr<drivers::Bluetooth> sBluetooth;
|
||||
|
||||
@@ -23,7 +23,8 @@ std::shared_ptr<drivers::NvsStorage> SystemState::sNvs;
|
||||
|
||||
std::shared_ptr<drivers::TouchWheel> SystemState::sTouch;
|
||||
std::shared_ptr<drivers::RelativeWheel> SystemState::sRelativeTouch;
|
||||
std::shared_ptr<drivers::Battery> SystemState::sBattery;
|
||||
std::shared_ptr<drivers::AdcBattery> SystemState::sAdc;
|
||||
std::shared_ptr<battery::Battery> SystemState::sBattery;
|
||||
std::shared_ptr<drivers::SdStorage> SystemState::sStorage;
|
||||
std::shared_ptr<drivers::Display> SystemState::sDisplay;
|
||||
std::shared_ptr<drivers::Bluetooth> SystemState::sBluetooth;
|
||||
@@ -95,16 +96,6 @@ void SystemState::react(const internal::SamdInterrupt&) {
|
||||
}
|
||||
}
|
||||
|
||||
void SystemState::react(const internal::BatteryTimerFired&) {
|
||||
ESP_LOGI(kTag, "checking battery");
|
||||
if (sBattery->UpdatePercent()) {
|
||||
ESP_LOGI(kTag, "battery now at %u%%", sBattery->Percent());
|
||||
BatteryPercentChanged ev{};
|
||||
events::Ui().Dispatch(ev);
|
||||
events::System().Dispatch(ev);
|
||||
}
|
||||
}
|
||||
|
||||
auto SystemState::IdleCondition() -> bool {
|
||||
return !sGpios->Get(drivers::IGpios::Pin::kKeyLock) &&
|
||||
audio::AudioState::is_in_state<audio::states::Standby>();
|
||||
|
||||
@@ -9,5 +9,5 @@ idf_component_register(
|
||||
"modal_progress.cpp" "modal.cpp" "modal_confirm.cpp" "screen_settings.cpp"
|
||||
"splash.c" "font_fusion.c" "font_symbols.c"
|
||||
INCLUDE_DIRS "include"
|
||||
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer")
|
||||
REQUIRES "drivers" "lvgl" "tinyfsm" "events" "system_fsm" "database" "esp_timer" "battery")
|
||||
target_compile_options(${COMPONENT_LIB} PRIVATE ${EXTRA_WARNINGS})
|
||||
|
||||
@@ -21,14 +21,15 @@ class Settings : public MenuScreen {
|
||||
public:
|
||||
Settings();
|
||||
~Settings();
|
||||
private:
|
||||
std::shared_ptr<Screen> bluetooth_;
|
||||
std::shared_ptr<Screen> headphones_;
|
||||
std::shared_ptr<Screen> appearance_;
|
||||
std::shared_ptr<Screen> input_method_;
|
||||
std::shared_ptr<Screen> storage_;
|
||||
std::shared_ptr<Screen> firmware_update_;
|
||||
std::shared_ptr<Screen> about_;
|
||||
|
||||
private:
|
||||
std::shared_ptr<Screen> bluetooth_;
|
||||
std::shared_ptr<Screen> headphones_;
|
||||
std::shared_ptr<Screen> appearance_;
|
||||
std::shared_ptr<Screen> input_method_;
|
||||
std::shared_ptr<Screen> storage_;
|
||||
std::shared_ptr<Screen> firmware_update_;
|
||||
std::shared_ptr<Screen> about_;
|
||||
};
|
||||
|
||||
class Bluetooth : public MenuScreen {
|
||||
@@ -36,32 +37,32 @@ class Bluetooth : public MenuScreen {
|
||||
Bluetooth();
|
||||
};
|
||||
|
||||
class Headphones : public MenuScreen {
|
||||
class Headphones : public MenuScreen {
|
||||
public:
|
||||
Headphones();
|
||||
};
|
||||
|
||||
class Appearance : public MenuScreen {
|
||||
class Appearance : public MenuScreen {
|
||||
public:
|
||||
Appearance();
|
||||
};
|
||||
|
||||
class InputMethod : public MenuScreen {
|
||||
class InputMethod : public MenuScreen {
|
||||
public:
|
||||
InputMethod();
|
||||
};
|
||||
|
||||
class Storage : public MenuScreen {
|
||||
class Storage : public MenuScreen {
|
||||
public:
|
||||
Storage();
|
||||
};
|
||||
|
||||
class FirmwareUpdate : public MenuScreen {
|
||||
class FirmwareUpdate : public MenuScreen {
|
||||
public:
|
||||
FirmwareUpdate();
|
||||
};
|
||||
|
||||
class About : public MenuScreen {
|
||||
class About : public MenuScreen {
|
||||
public:
|
||||
About();
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <stack>
|
||||
|
||||
#include "audio_events.hpp"
|
||||
#include "battery.hpp"
|
||||
#include "relative_wheel.hpp"
|
||||
#include "screen_playing.hpp"
|
||||
#include "tinyfsm.hpp"
|
||||
@@ -27,7 +28,9 @@ namespace ui {
|
||||
|
||||
class UiState : public tinyfsm::Fsm<UiState> {
|
||||
public:
|
||||
static auto Init(drivers::IGpios*, audio::TrackQueue*) -> bool;
|
||||
static auto Init(drivers::IGpios*,
|
||||
audio::TrackQueue*,
|
||||
std::shared_ptr<battery::Battery>) -> bool;
|
||||
|
||||
virtual ~UiState() {}
|
||||
|
||||
@@ -41,7 +44,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
|
||||
/* Fallback event handler. Does nothing. */
|
||||
void react(const tinyfsm::Event& ev) {}
|
||||
|
||||
void react(const system_fsm::BatteryPercentChanged&);
|
||||
void react(const system_fsm::BatteryStateChanged&);
|
||||
|
||||
virtual void react(const audio::PlaybackStarted&) {}
|
||||
virtual void react(const audio::PlaybackUpdate&) {}
|
||||
@@ -76,6 +79,7 @@ class UiState : public tinyfsm::Fsm<UiState> {
|
||||
static std::shared_ptr<drivers::TouchWheel> sTouchWheel;
|
||||
static std::shared_ptr<drivers::RelativeWheel> sRelativeWheel;
|
||||
static std::shared_ptr<drivers::Display> sDisplay;
|
||||
static std::shared_ptr<battery::Battery> sBattery;
|
||||
static std::weak_ptr<database::Database> sDb;
|
||||
|
||||
static std::stack<std::shared_ptr<Screen>> sScreens;
|
||||
|
||||
+11
-5
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "battery.hpp"
|
||||
#include "core/lv_obj.h"
|
||||
#include "misc/lv_gc.h"
|
||||
|
||||
@@ -43,16 +44,19 @@ audio::TrackQueue* UiState::sQueue;
|
||||
std::shared_ptr<drivers::TouchWheel> UiState::sTouchWheel;
|
||||
std::shared_ptr<drivers::RelativeWheel> UiState::sRelativeWheel;
|
||||
std::shared_ptr<drivers::Display> UiState::sDisplay;
|
||||
std::shared_ptr<battery::Battery> UiState::sBattery;
|
||||
std::weak_ptr<database::Database> UiState::sDb;
|
||||
|
||||
std::stack<std::shared_ptr<Screen>> UiState::sScreens;
|
||||
std::shared_ptr<Screen> UiState::sCurrentScreen;
|
||||
std::shared_ptr<Modal> UiState::sCurrentModal;
|
||||
|
||||
auto UiState::Init(drivers::IGpios* gpio_expander, audio::TrackQueue* queue)
|
||||
-> bool {
|
||||
auto UiState::Init(drivers::IGpios* gpio_expander,
|
||||
audio::TrackQueue* queue,
|
||||
std::shared_ptr<battery::Battery> battery) -> bool {
|
||||
sIGpios = gpio_expander;
|
||||
sQueue = queue;
|
||||
sBattery = battery;
|
||||
|
||||
lv_init();
|
||||
sDisplay.reset(
|
||||
@@ -100,15 +104,17 @@ void UiState::react(const system_fsm::KeyLockChanged& ev) {
|
||||
sRelativeWheel->SetEnabled(ev.falling);
|
||||
}
|
||||
|
||||
void UiState::react(const system_fsm::BatteryPercentChanged&) {
|
||||
void UiState::react(const system_fsm::BatteryStateChanged&) {
|
||||
UpdateTopBar();
|
||||
}
|
||||
|
||||
void UiState::UpdateTopBar() {
|
||||
auto battery_state = sBattery->State();
|
||||
widgets::TopBar::State state{
|
||||
.playback_state = widgets::TopBar::PlaybackState::kIdle,
|
||||
.battery_percent = 50,
|
||||
.is_charging = true,
|
||||
.battery_percent = static_cast<uint_fast8_t>(
|
||||
battery_state.has_value() ? battery_state->percent : 100),
|
||||
.is_charging = !battery_state.has_value() || battery_state->is_charging,
|
||||
};
|
||||
if (sCurrentScreen) {
|
||||
sCurrentScreen->UpdateTopBar(state);
|
||||
|
||||
+12
-11
@@ -65,17 +65,18 @@ auto TopBar::Update(const State& state) -> void {
|
||||
break;
|
||||
}
|
||||
|
||||
if (state.battery_percent >= 95) {
|
||||
lv_label_set_text(battery_, "100");
|
||||
} else if (state.battery_percent >= 70) {
|
||||
lv_label_set_text(battery_, ">70");
|
||||
} else if (state.battery_percent >= 40) {
|
||||
lv_label_set_text(battery_, ">40");
|
||||
} else if (state.battery_percent >= 10) {
|
||||
lv_label_set_text(battery_, ">10");
|
||||
} else {
|
||||
lv_label_set_text(battery_, "0");
|
||||
}
|
||||
lv_label_set_text(battery_, std::to_string(state.battery_percent).c_str());
|
||||
// if (state.battery_percent >= 95) {
|
||||
// lv_label_set_text(battery_, "100");
|
||||
// } else if (state.battery_percent >= 70) {
|
||||
// lv_label_set_text(battery_, ">70");
|
||||
// } else if (state.battery_percent >= 40) {
|
||||
// lv_label_set_text(battery_, ">40");
|
||||
// } else if (state.battery_percent >= 10) {
|
||||
// lv_label_set_text(battery_, ">10");
|
||||
// } else {
|
||||
// lv_label_set_text(battery_, "0");
|
||||
// }
|
||||
}
|
||||
|
||||
} // namespace widgets
|
||||
|
||||
Reference in New Issue
Block a user