diff --git a/README.md b/README.md index 7b3d846f..0733dd6c 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,8 @@ This project will not be actively maintained or regularly updated along with Atm - Sync ReverseNX Mode: No need to change clocks manually after toggling modes in ReverseNX - - View charger & battery info, toggle charging/fast-charging(2A) in overlay - - Extend battery life expectancy by maintaining battery charge at 40% - 60% and disabling fast charging if possible. - - Known issue: Fast charging toggle will be reset in-game. + - View charger & battery info, toggle fast-charging(2A) or set charge limit (20% - 100%) in overlay + - Note: Long-term use of charge limit may render the battery gauge inaccurate. Performing full cycles could help recalibration, or try [battery_desync_fix_nx](https://github.com/CTCaer/battery_desync_fix_nx). diff --git a/Source/sys-clk-OC/README.md b/Source/sys-clk-OC/README.md index f6fc2777..b38048b2 100644 --- a/Source/sys-clk-OC/README.md +++ b/Source/sys-clk-OC/README.md @@ -178,12 +178,13 @@ handheld_gpu=153 The `[values]` section allows you to alter timings in sys-clk, you should not need to edit any of these unless you know what you are doing. Possible values are: -| Key | Desc | Default | -|:-----------------------:|-------------------------------------------------------------------------------|:-------:| -|**allow_unsafe_freq** | Allow unsafe frequencies (CPU > 1963.5 MHz, GPU > 921.6 MHz) | OFF | -|**auto_cpu_boost** | Auto-boost CPU when system Core #3 utilization ≥ 95% | ON | -|**sync_reversenx_mode** | Sync nominal profile (mode) with ReverseNX (-Tool and -RT) | ON | -|**disable_fast_charging**| Disable Fast Charging (2000mA -> 500 mA) | OFF | -|**temp_log_interval_ms** | Defines how often sys-clk log temperatures, in milliseconds (`0` to disable) | 0 ms | -|**csv_write_interval_ms**| Defines how often sys-clk writes to the CSV, in milliseconds (`0` to disable) | 0 ms | -|**poll_interval_ms** | Defines how fast sys-clk checks and applies profiles, in milliseconds | 500 ms | +| Key | Desc | Default | +|:-----------------------:|-------------------------------------------------------------------------------|:---------:| +|**allow_unsafe_freq** | Allow unsafe frequencies (CPU > 1963.5 MHz, GPU > 921.6 MHz) | OFF | +|**auto_cpu_boost** | Auto-boost CPU when system Core #3 utilization ≥ 95% | ON | +|**sync_reversenx_mode** | Sync nominal profile (mode) with ReverseNX (-Tool and -RT) | ON | +|**disable_fast_charging**| Disable Fast Charging (2000mA -> 500 mA) | OFF | +|**charging_limit_perc** | Charging Limit (20% - 100%) | 100%(OFF) | +|**temp_log_interval_ms** | Defines how often sys-clk log temperatures, in milliseconds (`0` to disable) | 0 ms | +|**csv_write_interval_ms**| Defines how often sys-clk writes to the CSV, in milliseconds (`0` to disable) | 0 ms | +|**poll_interval_ms** | Defines how fast sys-clk checks and applies profiles, in milliseconds | 500 ms | diff --git a/Source/sys-clk-OC/common/include/sysclk/clocks.h b/Source/sys-clk-OC/common/include/sysclk/clocks.h index 1b4badcb..50357800 100644 --- a/Source/sys-clk-OC/common/include/sysclk/clocks.h +++ b/Source/sys-clk-OC/common/include/sysclk/clocks.h @@ -76,7 +76,7 @@ typedef struct typedef struct { union { - uint32_t mhz[SysClkProfile_EnumMax * SysClkModule_EnumMax]; + uint32_t mhz[(size_t)SysClkProfile_EnumMax * (size_t)SysClkModule_EnumMax]; uint32_t mhzMap[SysClkProfile_EnumMax][SysClkModule_EnumMax]; }; } SysClkTitleProfileList; diff --git a/Source/sys-clk-OC/overlay/Makefile b/Source/sys-clk-OC/overlay/Makefile index 35a25761..97d8b3b9 100644 --- a/Source/sys-clk-OC/overlay/Makefile +++ b/Source/sys-clk-OC/overlay/Makefile @@ -47,7 +47,7 @@ CFLAGS := -g -Wall -O2 -ffunction-sections \ CFLAGS += $(INCLUDE) -D__SWITCH__ -CXXFLAGS := $(CFLAGS) -fno-exceptions -std=gnu++17 +CXXFLAGS := $(CFLAGS) -fno-exceptions -std=gnu++20 ASFLAGS := -g $(ARCH) LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp index 3880a49e..13c55c48 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp +++ b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.cpp @@ -56,32 +56,34 @@ void MiscGui::listUI() this->syncModeToggle = addConfigToggle(SysClkConfigValue_SyncReverseNXMode, "Sync ReverseNX Mode"); this->fastChargingToggle = addConfigToggle(SysClkConfigValue_DisableFastCharging, "Disable Fast Charging"); - // this->chargingLimitHeader = new tsl::elm::CategoryHeader(""); - // this->listElement->addItem(this->chargingLimitHeader); - // this->chargingLimitBar = new MultiStepTrackBar("", 100 - 20 + 1); - // this->chargingLimitBar->setProgress((this->configList->values[SysClkConfigValue_ChargingLimitPercentage] - 20.0F) * 100 / (100 - 20)); - // this->chargingLimitBar->setValueChangedListener([this](u8 val) { - // this->configList->values[SysClkConfigValue_ChargingLimitPercentage] = val + 20; + this->chargingLimitHeader = new tsl::elm::CategoryHeader(""); + this->listElement->addItem(this->chargingLimitHeader); + this->chargingLimitBar = new StepTrackBarIcon("", 100 + 1); + this->chargingLimitBar->setProgress(this->configList->values[SysClkConfigValue_ChargingLimitPercentage]); + this->chargingLimitBar->setValueChangedListener([this](u8 val) { + if (val < 20) { + val = 20; + this->chargingLimitBar->setProgress(val); + } + this->configList->values[SysClkConfigValue_ChargingLimitPercentage] = val; - // snprintf(chargingLimitBarDesc, 50, "Battery Charging Limit: %lu%%", this->configList->values[SysClkConfigValue_ChargingLimitPercentage]); - // this->chargingLimitHeader->setText(chargingLimitBarDesc); - // Result rc = sysclkIpcSetConfigValues(this->configList); - // if (R_FAILED(rc)) - // FatalGui::openWithResultCode("sysclkIpcSetConfigValues", rc); + snprintf(chargingLimitBarDesc, 30, "Battery Charging Limit: %lu%%", this->configList->values[SysClkConfigValue_ChargingLimitPercentage]); + this->chargingLimitHeader->setText(chargingLimitBarDesc); + this->chargingLimitBar->setIcon(getBatteryStateIcon()); - // this->lastContextUpdate = armGetSystemTick(); - // }); - // this->listElement->addItem(this->chargingLimitBar); + Result rc = sysclkIpcSetConfigValues(this->configList); + if (R_FAILED(rc)) + FatalGui::openWithResultCode("sysclkIpcSetConfigValues", rc); + + this->lastContextUpdate = armGetSystemTick(); + }); + this->listElement->addItem(this->chargingLimitBar); + this->listElement->addItem(new tsl::elm::CustomDrawer([](tsl::gfx::Renderer* renderer, s32 x, s32 y, s32 w, s32 h) { + renderer->drawString("\uE016 Long-term use may render the battery gauge \ninaccurate!", false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR); + }), SMALL_TEXT_SIZE * 2 + 20); this->listElement->addItem(new tsl::elm::CategoryHeader("Temporary toggles")); - this->chargingToggle = new tsl::elm::ToggleListItem("Charging", false); - chargingToggle->setStateChangedListener([this](bool state) { - PsmChargingToggler(&state); - this->chargingToggle->setState(state); - }); - this->listElement->addItem(this->chargingToggle); - this->backlightToggle = new tsl::elm::ToggleListItem("Screen Backlight", false); backlightToggle->setStateChangedListener([this](bool state) { LblUpdate(true); @@ -90,8 +92,8 @@ void MiscGui::listUI() this->listElement->addItem(new tsl::elm::CategoryHeader("Battery & Charging Info")); this->listElement->addItem(new tsl::elm::CustomDrawer([this](tsl::gfx::Renderer *renderer, s32 x, s32 y, s32 w, s32 h) { - renderer->drawString(this->infoOutput, false, x, y, SMALL_TEXT_SIZE, DESC_COLOR); - }), SMALL_TEXT_SIZE * 13); + renderer->drawString(this->infoOutput, false, x, y + 20, SMALL_TEXT_SIZE, DESC_COLOR); + }), SMALL_TEXT_SIZE * 13 + 20); } void MiscGui::refresh() { @@ -106,15 +108,17 @@ void MiscGui::refresh() { updateConfigToggle(this->syncModeToggle, SysClkConfigValue_SyncReverseNXMode); updateConfigToggle(this->fastChargingToggle, SysClkConfigValue_DisableFastCharging); - // this->chargingLimitBar->setProgress(this->configList->values[SysClkConfigValue_ChargingLimitPercentage] - 20); - // snprintf(chargingLimitBarDesc, 50, "Battery Charging Limit: %u%%", u8(this->configList->values[SysClkConfigValue_ChargingLimitPercentage])); - // this->chargingLimitHeader->setText(chargingLimitBarDesc); + this->chargingLimitBar->setProgress(this->configList->values[SysClkConfigValue_ChargingLimitPercentage]); + snprintf(chargingLimitBarDesc, 30, "Battery Charging Limit: %lu%%", this->configList->values[SysClkConfigValue_ChargingLimitPercentage]); + this->chargingLimitHeader->setText(chargingLimitBarDesc); PsmUpdate(); + this->chargingLimitBar->setIcon(getBatteryStateIcon()); + LblUpdate(); this->backlightToggle->setState(lblstatus); + I2cGetInfo(this->i2cInfo); PrintInfo(this->infoOutput, sizeof(this->infoOutput)); - this->chargingToggle->setState(this->PsmIsCharging()); } } diff --git a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h index 65220b3e..8f958421 100644 --- a/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h +++ b/Source/sys-clk-OC/overlay/src/ui/gui/misc_gui.h @@ -13,21 +13,12 @@ #include "base_menu_gui.h" #include -class MultiStepTrackBar : public tsl::elm::StepTrackBar { +class StepTrackBarIcon : public tsl::elm::StepTrackBar { public: - MultiStepTrackBar(const char icon[3], size_t numSteps) - : tsl::elm::StepTrackBar(icon, numSteps) { } - - virtual ~MultiStepTrackBar() {} - - virtual inline u8 getProgress() override { - return this->m_value / (100.0F / (this->m_numSteps - 1)); - } - - virtual void setProgress(u8 value) override { - value = std::min(value, u8(this->m_numSteps - 1)); - this->m_value = value * (100.0F / (this->m_numSteps - 1)); - } + StepTrackBarIcon(const char icon[3], size_t numSteps): + tsl::elm::StepTrackBar(icon, numSteps) { } + const char* getIcon() { return this->m_icon; } + void setIcon(const char* icon) { this->m_icon = icon; } }; class MiscGui : public BaseMenuGui @@ -258,7 +249,7 @@ class MiscGui : public BaseMenuGui char chargeVoltLimit[20] = ""; if (chargeInfo->ChargeVoltageLimit) - snprintf(chargeVoltLimit, sizeof(chargeVoltLimit), ", %u mV", chargeInfo->ChargeVoltageLimit); + snprintf(chargeVoltLimit, sizeof(chargeVoltLimit), ", %umV", chargeInfo->ChargeVoltageLimit); char chargWattsInfo[50] = ""; if (chargeInfo->ChargerType) @@ -266,24 +257,24 @@ class MiscGui : public BaseMenuGui char batCurInfo[30] = ""; if (std::abs(i2cInfo->batCurrent) < 10) - snprintf(batCurInfo, sizeof(batCurInfo), "0 mA"); + snprintf(batCurInfo, sizeof(batCurInfo), "0mA"); else - snprintf(batCurInfo, sizeof(batCurInfo), "%+.2f mA (%+.2f W)", + snprintf(batCurInfo, sizeof(batCurInfo), "%+.2fmA (%+.2fW)", i2cInfo->batCurrent, i2cInfo->batCurrent * (float)chargeInfo->VoltageAvg / 1000'000); snprintf(out, outsize, "%s" "\nCharger: %s%s" "\nBattery: %.3fV %.2f\u00B0C" - "\nCurrent Limit: %u mA IN, %u mA OUT" - "\nCharging Limit: %u mA%s" + "\nCurrent Limit: +%umA, -%umA" + "\nCharging Limit: +%umA%s" "\nRaw Charge: %.2f%%" "\nBattery Age: %.2f%%" "\nPower Role: %s" "\nCurrent Flow: %s\n" - "\nCPU Volt: %d mV" - "\nGPU Volt: %d mV" - "\nDRAM Volt: %d mV" + "\nCPU Volt: %dmV" + "\nGPU Volt: %dmV" + "\nDRAM Volt: %dmV" , PsmIsEnoughPowerSupplied() ? "Enough Power Supplied" : "", ChargeInfoChargerTypeToStr(chargeInfo->ChargerType), chargWattsInfo, @@ -331,14 +322,40 @@ class MiscGui : public BaseMenuGui smExit(); } + typedef enum { + Discharging, + NotCharging, + SlowCharging, + FastCharging + } BatteryState; + + BatteryState getBatteryState() { + if (!PsmIsChargerConnected()) + return Discharging; + + if (!PsmIsCharging()) + return NotCharging; + + return chargeInfo->ChargeCurrentLimit > 768 ? FastCharging : SlowCharging; + } + + const char* getBatteryStateIcon() { + switch (getBatteryState()) { + case Discharging: return "\u25c0"; // ◀ + case NotCharging: return "\u2016"; // ‖ + case SlowCharging: return "\u25b6"; // ▶ + case FastCharging: return "\u25b6\u25b6"; // ▶▶ + default: return "?"; + } + } + tsl::elm::ToggleListItem* addConfigToggle(SysClkConfigValue, std::string); void updateConfigToggle(tsl::elm::ToggleListItem*, SysClkConfigValue); void updateLiftChargingLimitToggle(); tsl::elm::ToggleListItem *unsafeFreqToggle, *cpuBoostToggle, *syncModeToggle, *chargingToggle, *fastChargingToggle, *backlightToggle; - // tsl::elm::CategoryHeader *chargingLimitHeader; - // MultiStepTrackBar *chargingLimitBar; - // char chargingLimitBarDesc[50] = ""; + tsl::elm::CategoryHeader *chargingLimitHeader; + StepTrackBarIcon *chargingLimitBar; SysClkConfigValueList* configList; ChargeInfo* chargeInfo; @@ -346,5 +363,6 @@ class MiscGui : public BaseMenuGui LblBacklightSwitchStatus lblstatus = LblBacklightSwitchStatus_Disabled; bool isEnoughPowerSupplied = false; char infoOutput[800] = ""; - int frameCounter = 60; + char chargingLimitBarDesc[30] = ""; + u8 frameCounter = 60; }; diff --git a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp index e057356a..25a257bb 100644 --- a/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp +++ b/Source/sys-clk-OC/sysmodule/src/clock_manager.cpp @@ -358,22 +358,22 @@ void ClockManager::ChargingHandler() serviceDispatch(session, fastChargingConfig ? EnableFastBatteryCharging : DisableFastBatteryCharging); } - // bool isChargerConnected = (chargeInfoField->ChargerType != ChargerType_None); - // if (isChargerConnected) - // { - // u32 chargeNow = 0; - - // if (R_SUCCEEDED(psmGetBatteryChargePercentage(&chargeNow))) - // { - // bool isCharging = ((chargeInfoField->unk_x14 >> 8) & 1); - // u32 chargeLimit = this->GetConfig()->GetConfigValue(SysClkConfigValue_ChargingLimitPercentage); - // if (isCharging && chargeLimit < chargeNow) { - // serviceDispatch(session, DisableBatteryCharging); - // } else if (!isCharging && chargeNow < 100 && chargeLimit > chargeNow) { - // serviceDispatch(session, EnableBatteryCharging); - // } - // } - // } + u32 chargeLimit = this->GetConfig()->GetConfigValue(SysClkConfigValue_ChargingLimitPercentage); + bool isChargerConnected = (chargeInfoField->ChargerType != ChargerType_None); + if (isChargerConnected) + { + u32 chargeNow = 0; + if (R_SUCCEEDED(psmGetBatteryChargePercentage(&chargeNow))) + { + bool isCharging = ((chargeInfoField->unk_x14 >> 8) & 1); + if (isCharging && chargeLimit < chargeNow) { + serviceDispatch(session, DisableBatteryCharging); + } + if (!isCharging && chargeLimit > chargeNow) { + serviceDispatch(session, EnableBatteryCharging); + } + } + } delete chargeInfoField; psmExit(); diff --git a/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp b/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp index 9736c93c..29972c1f 100644 --- a/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp +++ b/Source/sys-clk-OC/sysmodule/src/ipc_service.cpp @@ -144,7 +144,7 @@ Result IpcService::ServiceHandlerFunc(void* arg, const IpcServerRequest* r, u8* break; case SysClkIpcCmd_GetConfigValues: - *out_dataSize = sizeof(SysClkTitleProfileList); + *out_dataSize = sizeof(SysClkConfigValueList); return ipcSrv->GetConfigValues((SysClkConfigValueList*)out_data); case SysClkIpcCmd_SetConfigValues: