diff --git a/Source/sys-clk/common/include/sysclk/board.h b/Source/sys-clk/common/include/sysclk/board.h index b3c8e527..16b709c9 100644 --- a/Source/sys-clk/common/include/sysclk/board.h +++ b/Source/sys-clk/common/include/sysclk/board.h @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -102,7 +102,7 @@ typedef enum SysClkPartLoad_EMC = 0, SysClkPartLoad_EMCCpu, HocClkPartLoad_GPU, - HocClkPartLoad_CPUAvg, + HocClkPartLoad_CPUMax, HocClkPartLoad_BAT, HocClkPartLoad_FAN, SysClkPartLoad_EnumMax diff --git a/Source/sys-clk/overlay/src/ui/gui/base_menu_gui.cpp b/Source/sys-clk/overlay/src/ui/gui/base_menu_gui.cpp index 6c510da6..7f001b4a 100644 --- a/Source/sys-clk/overlay/src/ui/gui/base_menu_gui.cpp +++ b/Source/sys-clk/overlay/src/ui/gui/base_menu_gui.cpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -36,13 +36,13 @@ BaseMenuGui::BaseMenuGui() : tempColors{ tsl::Color(0), tsl::Color(0), tsl::Colo this->context = nullptr; this->lastContextUpdate = 0; this->listElement = nullptr; - - + + // Pre-cache hardware model during initialization IsAula(); IsMariko(); IsHoag(); - + // Initialize display strings memset(displayStrings, 0, sizeof(displayStrings)); } @@ -55,14 +55,14 @@ BaseMenuGui::~BaseMenuGui() { void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { BaseGui::preDraw(renderer); if(!this->context) [[unlikely]] return; - + // All constants pre-calculated and cached static constexpr const char* const labels[] = { "App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN", "DISP" }; static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1}; - + static u32 labelWidths[10]; static bool positionsInitialized = false; @@ -77,29 +77,29 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { static u32 maxProfileValueWidth = renderer->getTextDimensions("PD Charger", false, SMALL_TEXT_SIZE).first; // longest word u32 y = 91; - + // === TOP SECTION === renderer->drawRoundedRect(14, 70-1, 420, 30+2, 15.0f, renderer->aWithOpacity(tsl::tableBGColor)); - + // App ID - use pre-formatted string renderer->drawString(labels[0], false, positions[0], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(displayStrings[0], false, positions[0] + labelWidths[0] + 9, y, SMALL_TEXT_SIZE, tsl::infoTextColor); - + // Profile - use pre-formatted string renderer->drawString(labels[1], false, 423 - maxProfileValueWidth - labelWidths[1] - 9, y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(displayStrings[1], false, 423 - maxProfileValueWidth, y, SMALL_TEXT_SIZE, tsl::infoTextColor); - + y = 129; // Direct assignment instead of += 38 - + // === MAIN DATA SECTION === renderer->drawRoundedRect(14, 106, 420, 156, 10.0f, renderer->aWithOpacity(tsl::tableBGColor)); - + // === FREQUENCY SECTION === // Labels first (better cache locality) renderer->drawString(labels[2], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(labels[3], false, positions[3], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(labels[4], false, positions[4], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); - + // Current frequencies - use pre-formatted strings renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU @@ -107,7 +107,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { y = 149; // Direct assignment (129 + 20) - // renderer->drawString(displayStrings[19], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU Usage + renderer->drawString(displayStrings[19], false, positions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU Usage renderer->drawString(displayStrings[17], false, positions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU Usage renderer->drawString(displayStrings[18], false, positions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // RAM Usage @@ -115,39 +115,39 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) { renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real renderer->drawString(displayStrings[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real renderer->drawString(displayStrings[7], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM real - + y = 169; // Direct assignment (149 + 20) - + // === VOLTAGES === renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage renderer->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor); - + y = 191; // Direct assignment (169 + 22) - + // === TEMPERATURE SECTION === // Labels renderer->drawString(labels[5], false, positions[5], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(labels[6], false, positions[6]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(labels[7], false, positions[7], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); - + // Temperatures with color - use pre-computed colors renderer->drawString(displayStrings[11], false, dataPositions[0], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_SOC]); // SOC renderer->drawString(displayStrings[12], false, dataPositions[1], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_PCB]); // PCB renderer->drawString(displayStrings[13], false, dataPositions[2], y, SMALL_TEXT_SIZE, tempColors[SysClkThermalSensor_Skin]); // Skin - + y = 211; // Direct assignment (191 + 20) - + renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); - + // Power labels and values renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor); renderer->drawString(labels[9], false, positions[9], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); - + renderer->drawString(displayStrings[15], false, dataPositions[3], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power now renderer->drawString(displayStrings[16], false, dataPositions[4], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Power avg - + y+=20; renderer->drawString(labels[10], false, positions[2], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); @@ -181,9 +181,9 @@ void BaseMenuGui::refresh() if (armTicksToNs(ticks - this->lastContextUpdate) <= 1000000000UL) [[likely]] { return; // Early exit for most calls } - + this->lastContextUpdate = ticks; - + // Lazy context allocation if (!this->context) [[unlikely]] { this->context = new SysClkContext; @@ -206,30 +206,30 @@ void BaseMenuGui::refresh() // === FORMAT ALL DISPLAY STRINGS (once per second) === // App ID (hex conversion) sprintf(displayStrings[0], "%016lX", context->applicationId); - + // Profile strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true)); - + // Current frequencies u32 hz = context->freqs[SysClkModule_CPU]; // CPU sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); - + hz = context->freqs[SysClkModule_GPU]; // GPU sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); hz = context->freqs[SysClkModule_MEM]; // MEM sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); - + // Real frequencies hz = context->realFreqs[SysClkModule_CPU]; // CPU sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); - + hz = context->realFreqs[SysClkModule_GPU]; // GPU sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); - + hz = context->realFreqs[SysClkModule_MEM]; // MEM sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U); - + // Voltages sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0); sprintf(displayStrings[9], "%.1f mV", context->voltages[HocClkVoltage_GPU] / 1000.0); @@ -243,31 +243,30 @@ void BaseMenuGui::refresh() //sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U); sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDD2] / 1000U); } - + // Temperatures and pre-compute colors u32 millis = context->temps[SysClkThermalSensor_SOC]; // SOC sprintf(displayStrings[11], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); tempColors[SysClkThermalSensor_SOC] = tsl::GradientColor(millis * 0.001f); - + millis = context->temps[SysClkThermalSensor_PCB]; // PCB sprintf(displayStrings[12], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); tempColors[SysClkThermalSensor_PCB] = tsl::GradientColor(millis * 0.001f); - + millis = context->temps[SysClkThermalSensor_Skin]; // Skin sprintf(displayStrings[13], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); tempColors[SysClkThermalSensor_Skin] = tsl::GradientColor(millis * 0.001f); - + // SOC voltage (if available) sprintf(displayStrings[14], "%u mV", context->voltages[HocClkVoltage_SOC] / 1000U); - + // Power sprintf(displayStrings[15], "%d mW", context->power[0]); // Now sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg - sprintf(displayStrings[17], "%u%%", context->partLoad[HocClkPartLoad_GPU] / 10); sprintf(displayStrings[18], "%u%%", context->partLoad[SysClkPartLoad_EMC] / 10); - // sprintf(displayStrings[19], "%u", context->partLoad[HocClkPartLoad_CPUAvg]); + sprintf(displayStrings[19], "%u%%", context->partLoad[HocClkPartLoad_CPUMax] / 10); millis = context->temps[HorizonOCThermalSensor_Battery]; // Battery sprintf(displayStrings[20], "%u.%u °C", millis / 1000U, (millis % 1000U) / 100U); diff --git a/Source/sys-clk/sysmodule/perms.json b/Source/sys-clk/sysmodule/perms.json index 5c490dca..7fa6bdaa 100644 --- a/Source/sys-clk/sysmodule/perms.json +++ b/Source/sys-clk/sysmodule/perms.json @@ -4,7 +4,7 @@ "title_id_range_min": "0x00FF0000636C6BFF", "title_id_range_max": "0x00FF0000636C6BFF", "main_thread_stack_size": "0x00008000", - "main_thread_priority": 63, + "main_thread_priority": 16, "default_cpu_id": 3, "process_category": 0, "is_retail": true, @@ -25,7 +25,7 @@ "type": "kernel_flags", "value": { "highest_thread_priority": 63, - "lowest_thread_priority": 41, + "lowest_thread_priority": 16, "lowest_cpu_id": 0, "highest_cpu_id": 3 } diff --git a/Source/sys-clk/sysmodule/src/board.cpp b/Source/sys-clk/sysmodule/src/board.cpp index c910424f..1f5e1411 100644 --- a/Source/sys-clk/sysmodule/src/board.cpp +++ b/Source/sys-clk/sysmodule/src/board.cpp @@ -66,11 +66,12 @@ #define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0)) #define NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD 0x80044715 -#define systemtickfrequency 19200000 -#define systemtickfrequencyF 19200000.0f -#define CPU_TICK_WAIT (1'000'000'000 / 60) +constexpr u64 CpuTimeOutNs = 500'000'000; +constexpr double Systemtickfrequency = 19200000.0 * (static_cast(CpuTimeOutNs) / 1'000'000'000.0); + Result nvCheck = 1; +LEvent threadexit; Thread gpuLThread; Thread cpuCore0Thread; Thread cpuCore1Thread; @@ -91,10 +92,11 @@ BatteryChargeInfo info; static SysClkSocType g_socType = SysClkSocType_Erista; static HorizonOCConsoleType g_consoleType = HorizonOCConsoleType_Iowa; -std::atomic idletick0{systemtickfrequency}; -std::atomic idletick1{systemtickfrequency}; -std::atomic idletick2{systemtickfrequency}; -std::atomic idletick3{systemtickfrequency}; +u64 idletick0 = 0; +u64 idletick1 = 0; +u64 idletick2 = 0; +// u64 idletick3 = 0; + u32 cpu0, cpu1, cpu2, cpu3, cpuAvg; u16 cpuSpeedo0, cpuSpeedo2, socSpeedo0; // CPU, GPU, SOC u32 speedoBracket; @@ -164,16 +166,16 @@ PcvModuleId Board::GetPcvModuleId(SysClkModule sysclkModule) return pcvModuleId; } -void CheckCore(void* idletick_ptr) { - std::atomic* idletick = (std::atomic*)idletick_ptr; - while (true) { - uint64_t idletick_a; - uint64_t idletick_b; - svcGetInfo(&idletick_b, InfoType_IdleTickCount, INVALID_HANDLE, -1); - svcSleepThread(CPU_TICK_WAIT); - svcGetInfo(&idletick_a, InfoType_IdleTickCount, INVALID_HANDLE, -1); - idletick->store(idletick_a - idletick_b, std::memory_order_release); - } +void CheckCore(void *idletickPtr) { + u64* idletick = static_cast(idletickPtr); + while(true) { + u64 idletickA; + u64 idletickB; + svcGetInfo(&idletickB, InfoType_IdleTickCount, INVALID_HANDLE, -1); + svcWaitForAddress(&threadexit, ArbitrationType_WaitIfEqual, 0, CpuTimeOutNs); + svcGetInfo(&idletickA, InfoType_IdleTickCount, INVALID_HANDLE, -1); + *idletick = idletickA - idletickB; + } } void gpuLoadThread(void*) { @@ -205,7 +207,6 @@ void miscThreadFunc(void*) { } } - void Board::Initialize() { Result rc = 0; @@ -253,17 +254,17 @@ void Board::Initialize() threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2); threadStart(&gpuLThread); - - threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x500, 0x10, 0); - threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x500, 0x10, 1); - threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x500, 0x10, 2); - threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x500, 0x10, 3); - threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x3F, 3); + leventClear(&threadexit); + threadCreate(&cpuCore0Thread, CheckCore, &idletick0, NULL, 0x1000, 0x10, 0); + threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1); + threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2); + // threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3); + threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x10, 3); threadStart(&cpuCore0Thread); threadStart(&cpuCore1Thread); threadStart(&cpuCore2Thread); - threadStart(&cpuCore3Thread); + // threadStart(&cpuCore3Thread); threadStart(&miscThread); batteryInfoInitialize(); @@ -393,7 +394,7 @@ void Board::Exit() threadClose(&cpuCore0Thread); threadClose(&cpuCore1Thread); threadClose(&cpuCore2Thread); - threadClose(&cpuCore3Thread); + // threadClose(&cpuCore3Thread); threadClose(&miscThread); pwmChannelSessionClose(&g_ICon); @@ -776,6 +777,15 @@ std::int32_t Board::GetPowerMw(SysClkPowerSensor sensor) return 0; } +u32 GetMaxCpuLoad() { + float cpuUsage0 = std::clamp(((Systemtickfrequency - idletick0) / static_cast(Systemtickfrequency)) * 1000.0, 0.0, 1000.0); + float cpuUsage1 = std::clamp(((Systemtickfrequency - idletick1) / static_cast(Systemtickfrequency)) * 1000.0, 0.0, 1000.0); + float cpuUsage2 = std::clamp(((Systemtickfrequency - idletick2) / static_cast(Systemtickfrequency)) * 1000.0, 0.0, 1000.0); + // float cpuUsage3 = std::clamp(((Systemtickfrequency - idletick3) / static_cast(Systemtickfrequency)) * 1000.0, 0.0, 1000.0); + + return std::round(std::max({cpuUsage0, cpuUsage1, cpuUsage2})); +} + std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource) { switch(loadSource) @@ -786,8 +796,8 @@ std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource) return t210EmcLoadCpu(); case HocClkPartLoad_GPU: return GPU_Load_u; - case HocClkPartLoad_CPUAvg: - return idletick0; + case HocClkPartLoad_CPUMax: + return GetMaxCpuLoad(); case HocClkPartLoad_BAT: batteryInfoGetChargeInfo(&info); return info.RawBatteryCharge; diff --git a/Source/sys-clk/sysmodule/src/main.cpp b/Source/sys-clk/sysmodule/src/main.cpp index 1c34a2c4..bf0fec36 100644 --- a/Source/sys-clk/sysmodule/src/main.cpp +++ b/Source/sys-clk/sysmodule/src/main.cpp @@ -12,9 +12,9 @@ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . - * + * */ - + /* -------------------------------------------------------------------------- * "THE BEER-WARE LICENSE" (Revision 42): * , , @@ -36,7 +36,7 @@ #include "process_management.h" #include "clock_manager.h" #include "ipc_service.h" -#define INNER_HEAP_SIZE 0x30000 +#define INNER_HEAP_SIZE 0x34000 extern "C" { @@ -80,11 +80,11 @@ extern "C" hosversionSet(MAKEHOSVERSION(fw.major, fw.minor, fw.micro)); setsysExit(); } - + // rc = fanInitialize(); // if (R_FAILED(rc)) // diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); - + rc = i2cInitialize(); if (R_FAILED(rc)) diagAbortWithResult(MAKERESULT(Module_Libnx, LibnxError_ShouldNotHappen)); @@ -96,7 +96,7 @@ extern "C" // fanExit(); i2cExit(); fsExit(); - fsdevUnmountAll(); + fsdevUnmountAll(); } } @@ -154,6 +154,6 @@ int main(int argc, char** argv) FileUtils::LogLine("Exit"); svcSleepThread(1000000ULL); FileUtils::Exit(); - + return 0; }