sysmodule/overlay: re-add part load, voltage readings and animated logo
This commit is contained in:
@@ -47,9 +47,19 @@ typedef enum
|
|||||||
HorizonOCConsoleType_Lite,
|
HorizonOCConsoleType_Lite,
|
||||||
HorizonOCConsoleType_UnreleasedMariko,
|
HorizonOCConsoleType_UnreleasedMariko,
|
||||||
HorizonOCConsoleType_OLED,
|
HorizonOCConsoleType_OLED,
|
||||||
SysClkSocType_EnumMax
|
HorizonOCConsoleType_EnumMax,
|
||||||
} HorizonOCConsoleType;
|
} HorizonOCConsoleType;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
HocClkVoltage_SOC = 0,
|
||||||
|
HocClkVoltage_EMCVDD2,
|
||||||
|
HocClkVoltage_CPU,
|
||||||
|
HocClkVoltage_GPU,
|
||||||
|
HocClkVoltage_EMCVDDQ_MarikoOnly,
|
||||||
|
HocClkVoltage_Display,
|
||||||
|
HocClkVoltage_EnumMax,
|
||||||
|
} HocClkVoltage;
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SysClkProfile_Handheld = 0,
|
SysClkProfile_Handheld = 0,
|
||||||
@@ -85,10 +95,13 @@ typedef enum
|
|||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
SysClkRamLoad_All = 0,
|
SysClkPartLoad_EMC = 0,
|
||||||
SysClkRamLoad_Cpu,
|
SysClkPartLoad_EMCCpu,
|
||||||
SysClkRamLoad_EnumMax
|
HocClkPartLoad_GPU,
|
||||||
} SysClkRamLoad;
|
HocClkPartLoad_CPUAvg,
|
||||||
|
SysClkPartLoad_EnumMax
|
||||||
|
} SysClkPartLoad;
|
||||||
|
|
||||||
|
|
||||||
typedef enum
|
typedef enum
|
||||||
{
|
{
|
||||||
@@ -162,3 +175,25 @@ static inline const char* sysclkFormatProfile(SysClkProfile profile, bool pretty
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static inline const char* hocClkFormatVoltage(HocClkVoltage voltage, bool pretty)
|
||||||
|
{
|
||||||
|
switch(voltage)
|
||||||
|
{
|
||||||
|
case HocClkVoltage_CPU:
|
||||||
|
return pretty ? "CPU" : "cpu";
|
||||||
|
case HocClkVoltage_GPU:
|
||||||
|
return pretty ? "GPU" : "gpu";
|
||||||
|
case HocClkVoltage_EMCVDD2:
|
||||||
|
return pretty ? "VDD2" : "emcvdd2";
|
||||||
|
case HocClkVoltage_EMCVDDQ_MarikoOnly:
|
||||||
|
return pretty ? "VDDQ" : "vddq";
|
||||||
|
case HocClkVoltage_SOC:
|
||||||
|
return pretty ? "SOC" : "soc";
|
||||||
|
case HocClkVoltage_Display:
|
||||||
|
return pretty ? "SOC" : "soc";
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -40,7 +40,8 @@ typedef struct
|
|||||||
uint32_t overrideFreqs[SysClkModule_EnumMax];
|
uint32_t overrideFreqs[SysClkModule_EnumMax];
|
||||||
uint32_t temps[SysClkThermalSensor_EnumMax];
|
uint32_t temps[SysClkThermalSensor_EnumMax];
|
||||||
int32_t power[SysClkPowerSensor_EnumMax];
|
int32_t power[SysClkPowerSensor_EnumMax];
|
||||||
uint32_t ramLoad[SysClkRamLoad_EnumMax];
|
uint32_t PartLoad[SysClkPartLoad_EnumMax];
|
||||||
|
uint32_t voltages[HocClkVoltage_EnumMax];
|
||||||
uint32_t perfConfId;
|
uint32_t perfConfId;
|
||||||
} SysClkContext;
|
} SysClkContext;
|
||||||
|
|
||||||
|
|||||||
@@ -120,9 +120,6 @@ static inline const char* sysclkFormatConfigValue(SysClkConfigValue val, bool pr
|
|||||||
case HocClkConfigValue_LiteTDPLimit:
|
case HocClkConfigValue_LiteTDPLimit:
|
||||||
return pretty ? "Lite TDP Limit" : "tdp_limit_l";
|
return pretty ? "Lite TDP Limit" : "tdp_limit_l";
|
||||||
|
|
||||||
case HocClkConfigValue_TDPCycleLimit:
|
|
||||||
return pretty ? "TDP Cycle Limit" : "tdp_limit_c";
|
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return pretty ? "Null" : "null";
|
return pretty ? "Null" : "null";
|
||||||
}
|
}
|
||||||
@@ -166,8 +163,6 @@ static inline uint64_t sysclkDefaultConfigValue(SysClkConfigValue val)
|
|||||||
return 8600ULL;
|
return 8600ULL;
|
||||||
case HocClkConfigValue_LiteTDPLimit:
|
case HocClkConfigValue_LiteTDPLimit:
|
||||||
return 6400ULL;
|
return 6400ULL;
|
||||||
case HocClkConfigValue_TDPCycleLimit:
|
|
||||||
return 10ULL;
|
|
||||||
default:
|
default:
|
||||||
return 0ULL;
|
return 0ULL;
|
||||||
}
|
}
|
||||||
@@ -192,8 +187,6 @@ static inline uint64_t sysclkValidConfigValue(SysClkConfigValue val, uint64_t in
|
|||||||
case SysClkConfigValue_FreqLogIntervalMs:
|
case SysClkConfigValue_FreqLogIntervalMs:
|
||||||
case SysClkConfigValue_PowerLogIntervalMs:
|
case SysClkConfigValue_PowerLogIntervalMs:
|
||||||
case SysClkConfigValue_CsvWriteIntervalMs:
|
case SysClkConfigValue_CsvWriteIntervalMs:
|
||||||
case HocClkConfigValue_TDPCycleLimit:
|
|
||||||
return input >= 0;
|
|
||||||
case HocClkConfigValue_UncappedClocks:
|
case HocClkConfigValue_UncappedClocks:
|
||||||
case HocClkConfigValue_OverwriteBoostMode:
|
case HocClkConfigValue_OverwriteBoostMode:
|
||||||
case HocClkConfigValue_ThermalThrottle:
|
case HocClkConfigValue_ThermalThrottle:
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
*
|
*
|
||||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
* more details.
|
* for more details.
|
||||||
*
|
*
|
||||||
* You should have received a copy of the GNU General Public License
|
* You should have received a copy of the GNU General Public License
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/* --------------------------------------------------------------------------
|
/* --------------------------------------------------------------------------
|
||||||
* "THE BEER-WARE LICENSE" (Revision 42):
|
* "THE BEER-WARE LICENSE" (Revision 42):
|
||||||
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
* <p-sam@d3vs.net>, <natinusala@gmail.com>, <m4x@m4xw.net>
|
||||||
@@ -24,39 +24,141 @@
|
|||||||
* --------------------------------------------------------------------------
|
* --------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include "base_gui.h"
|
#include "base_gui.h"
|
||||||
|
|
||||||
#include "../elements/base_frame.h"
|
#include "../elements/base_frame.h"
|
||||||
#include "logo_rgba_bin.h"
|
#include "logo_rgba_bin.h"
|
||||||
|
|
||||||
|
#include <tesla.hpp>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#define LOGO_X 20
|
#define LOGO_X 20
|
||||||
#define LOGO_Y 45
|
#define LOGO_Y 50
|
||||||
#define LOGO_LABEL_FONT_SIZE 35
|
#define LOGO_LABEL_FONT_SIZE 45
|
||||||
|
|
||||||
#define VERSION_X (LOGO_X + 250)
|
#define VERSION_X (LOGO_X + 250)
|
||||||
#define VERSION_Y LOGO_Y-40
|
#define VERSION_Y (LOGO_Y - 40)
|
||||||
#define VERSION_FONT_SIZE 15
|
#define VERSION_FONT_SIZE 15
|
||||||
|
|
||||||
std::string getVersionString() {
|
std::string getVersionString() {
|
||||||
char buf[0x100] = ""; // 256 bytes — safe for any expected version string
|
char buf[0x100] = "";
|
||||||
Result rc = sysclkIpcGetVersionString(buf, sizeof(buf));
|
Result rc = sysclkIpcGetVersionString(buf, sizeof(buf));
|
||||||
if (R_FAILED(rc) || buf[0] == '\0') {
|
if (R_FAILED(rc) || buf[0] == '\0') {
|
||||||
return "unknown";
|
return "HorizonOC-Misc";
|
||||||
}
|
}
|
||||||
return std::string(buf);
|
return std::string(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
// ---------------------------------------------
|
||||||
|
// AQUATIC BLUE COLORS (4-bit color space)
|
||||||
|
// ---------------------------------------------
|
||||||
|
static constexpr tsl::Color dynamicLogoRGB1 = tsl::Color(0, 4, 8, 15); // Deep ocean blue
|
||||||
|
static constexpr tsl::Color dynamicLogoRGB2 = tsl::Color(7, 15, 15, 15); // Bright aqua cyan
|
||||||
|
static constexpr tsl::Color STATIC_AQUA = tsl::Color(2, 10, 12, 15); // Mid aqua
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// FULLY ENHANCED ANIMATED LOGO EFFECT
|
||||||
|
// ---------------------------------------------
|
||||||
|
static s32 drawDynamicUltraText(
|
||||||
|
tsl::gfx::Renderer* renderer,
|
||||||
|
s32 startX,
|
||||||
|
s32 y,
|
||||||
|
u32 fontSize,
|
||||||
|
const tsl::Color& staticColor,
|
||||||
|
bool useNotificationMethod = false)
|
||||||
{
|
{
|
||||||
// renderer->drawBitmap(LOGO_X, LOGO_Y, LOGO_WIDTH, LOGO_HEIGHT, logo_rgba_bin);
|
static constexpr double cycleDuration = 1.6;
|
||||||
renderer->drawString("Horizon OC overlay", false, LOGO_X, LOGO_Y, LOGO_LABEL_FONT_SIZE, renderer->a(TEXT_COLOR));
|
|
||||||
// renderer->drawString(TARGET_VERSION, false, VERSION_X, VERSION_Y, VERSION_FONT_SIZE, tsl::bannerVersionTextColor);
|
const std::string name = "Horizon OC Zeus";
|
||||||
|
s32 currentX = startX;
|
||||||
|
|
||||||
|
const u64 currentTime_ns = armTicksToNs(armGetSystemTick());
|
||||||
|
const double timeNow = static_cast<double>(currentTime_ns) / 1e9;
|
||||||
|
const double timeBase = fmod(timeNow, cycleDuration);
|
||||||
|
|
||||||
|
const double waveScale = 2.0 * M_PI / cycleDuration;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < name.size(); i++)
|
||||||
|
{
|
||||||
|
char letter = name[i];
|
||||||
|
if (letter == '\0') break;
|
||||||
|
|
||||||
|
double phase = waveScale * (timeBase + i * 0.12);
|
||||||
|
|
||||||
|
double raw = cos(phase);
|
||||||
|
double n = (raw + 1.0) * 0.5;
|
||||||
|
double s1 = n * n * (3.0 - 2.0 * n);
|
||||||
|
double blend = std::clamp(s1, 0.0, 1.0);
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// Glow Pulse (brightness modulation)
|
||||||
|
// ---------------------------------------------
|
||||||
|
double glow = (cos(phase * 1.5) + 1.0) * 0.5;
|
||||||
|
double brightness = 0.75 + glow * 0.25;
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// Color interpolation (4-bit!)
|
||||||
|
// ---------------------------------------------
|
||||||
|
u8 r = static_cast<u8>(
|
||||||
|
(dynamicLogoRGB1.r + (dynamicLogoRGB2.r - dynamicLogoRGB1.r) * blend) * brightness
|
||||||
|
);
|
||||||
|
u8 g = static_cast<u8>(
|
||||||
|
(dynamicLogoRGB1.g + (dynamicLogoRGB2.g - dynamicLogoRGB1.g) * blend) * brightness
|
||||||
|
);
|
||||||
|
u8 b = static_cast<u8>(
|
||||||
|
(dynamicLogoRGB1.b + (dynamicLogoRGB2.b - dynamicLogoRGB1.b) * blend) * brightness
|
||||||
|
);
|
||||||
|
|
||||||
|
r = std::clamp<u8>(r, 0, 15);
|
||||||
|
g = std::clamp<u8>(g, 0, 15);
|
||||||
|
b = std::clamp<u8>(b, 0, 15);
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// ZEUS Lightning Flash
|
||||||
|
// ---------------------------------------------
|
||||||
|
bool lightning = (fmod(timeNow, 5.0) < 0.15);
|
||||||
|
if (lightning) {
|
||||||
|
r = std::min<u8>(r + 4, 15);
|
||||||
|
g = std::min<u8>(g + 4, 15);
|
||||||
|
b = std::min<u8>(b + 15, 15); // strong blue spike
|
||||||
|
}
|
||||||
|
|
||||||
|
tsl::Color color(r, g, b, 15);
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// Vertical Water Wobble
|
||||||
|
// ---------------------------------------------
|
||||||
|
s32 wobbleY = y + sin(phase) * 3;
|
||||||
|
|
||||||
|
std::string ls(1, letter);
|
||||||
|
|
||||||
|
if (useNotificationMethod)
|
||||||
|
currentX += renderer->drawNotificationString(ls, false, currentX, wobbleY, fontSize, color).first;
|
||||||
|
else
|
||||||
|
currentX += renderer->drawString(ls, false, currentX, wobbleY, fontSize, color).first;
|
||||||
|
}
|
||||||
|
|
||||||
|
return currentX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// PRE-DRAW HOOK
|
||||||
|
// ---------------------------------------------
|
||||||
|
void BaseGui::preDraw(tsl::gfx::Renderer* renderer)
|
||||||
|
{
|
||||||
|
drawDynamicUltraText(
|
||||||
|
renderer,
|
||||||
|
LOGO_X,
|
||||||
|
LOGO_Y,
|
||||||
|
LOGO_LABEL_FONT_SIZE,
|
||||||
|
STATIC_AQUA,
|
||||||
|
false
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// UI SETUP
|
||||||
|
// ---------------------------------------------
|
||||||
tsl::elm::Element* BaseGui::createUI()
|
tsl::elm::Element* BaseGui::createUI()
|
||||||
{
|
{
|
||||||
BaseFrame* rootFrame = new BaseFrame(this);
|
BaseFrame* rootFrame = new BaseFrame(this);
|
||||||
@@ -64,6 +166,9 @@ tsl::elm::Element* BaseGui::createUI()
|
|||||||
return rootFrame;
|
return rootFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------
|
||||||
|
// LIVE UPDATE
|
||||||
|
// ---------------------------------------------
|
||||||
void BaseGui::update()
|
void BaseGui::update()
|
||||||
{
|
{
|
||||||
this->refresh();
|
this->refresh();
|
||||||
|
|||||||
@@ -37,8 +37,6 @@ BaseMenuGui::BaseMenuGui() : tempColors{tsl::Color(0), tsl::Color(0), tsl::Color
|
|||||||
this->lastContextUpdate = 0;
|
this->lastContextUpdate = 0;
|
||||||
this->listElement = nullptr;
|
this->listElement = nullptr;
|
||||||
|
|
||||||
// Initialize all voltages to zero once
|
|
||||||
memset(&cpuVoltageUv, 0, sizeof(u32) * 5); // Zero all 5 voltage values at once
|
|
||||||
|
|
||||||
// Pre-cache hardware model during initialization
|
// Pre-cache hardware model during initialization
|
||||||
IsMariko();
|
IsMariko();
|
||||||
@@ -104,9 +102,12 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
renderer->drawString(displayStrings[2], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU
|
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
|
renderer->drawString(displayStrings[3], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU
|
||||||
renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
|
renderer->drawString(displayStrings[4], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // MEM
|
||||||
|
|
||||||
y = 149; // Direct assignment (129 + 20)
|
y = 149; // Direct assignment (129 + 20)
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
// === REAL FREQUENCIES ===
|
// === REAL FREQUENCIES ===
|
||||||
renderer->drawString(displayStrings[5], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU real
|
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[6], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU real
|
||||||
@@ -117,15 +118,8 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
// === VOLTAGES ===
|
// === VOLTAGES ===
|
||||||
renderer->drawString(displayStrings[8], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // CPU voltage
|
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->drawString(displayStrings[9], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // GPU voltage
|
||||||
|
|
||||||
// Memory voltage - check if VDD is present
|
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
|
||||||
if (emcVoltageUv && vddVoltageUv) {
|
|
||||||
renderer->drawStringWithColoredSections(displayStrings[10], false, {""}, dataPositions[5]-16, y, SMALL_TEXT_SIZE, tsl::infoTextColor, tsl::separatorColor);
|
|
||||||
} else if (vddVoltageUv) {
|
|
||||||
renderer->drawString(displayStrings[10], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
|
||||||
} else if (emcVoltageUv) {
|
|
||||||
renderer->drawString(displayStrings[10], false, dataPositions[2], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
y = 191; // Direct assignment (169 + 22)
|
y = 191; // Direct assignment (169 + 22)
|
||||||
|
|
||||||
@@ -142,11 +136,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
|
|
||||||
y = 211; // Direct assignment (191 + 20)
|
y = 211; // Direct assignment (191 + 20)
|
||||||
|
|
||||||
// === SOC VOLTAGE & POWER ===
|
renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
||||||
// SOC voltage (if available)
|
|
||||||
if (socVoltageUv) [[likely]] {
|
|
||||||
renderer->drawString(displayStrings[14], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Power labels and values
|
// Power labels and values
|
||||||
renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
renderer->drawString(labels[8], false, positions[8]-1, y, SMALL_TEXT_SIZE, tsl::sectionTextColor);
|
||||||
@@ -172,59 +162,6 @@ void BaseMenuGui::refresh()
|
|||||||
this->context = new SysClkContext;
|
this->context = new SysClkContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
// === ULTRA-FAST VOLTAGE READING ===
|
|
||||||
// Pre-computed domain configuration based on hardware
|
|
||||||
static const PowerDomainId domains[] = {
|
|
||||||
PcvPowerDomainId_Max77621_Cpu, // [0] CPU
|
|
||||||
PcvPowerDomainId_Max77621_Gpu, // [1] GPU
|
|
||||||
PcvPowerDomainId_Max77812_Dram, // [2] EMC/DRAM - Mariko only
|
|
||||||
PcvPowerDomainId_Max77620_Sd0, // [3] SOC - EOS only
|
|
||||||
PcvPowerDomainId_Max77620_Sd1 // [4] VDD2 - EOS only
|
|
||||||
};
|
|
||||||
|
|
||||||
// Voltage array for direct indexing
|
|
||||||
u32* voltages[] = {&cpuVoltageUv, &gpuVoltageUv, &emcVoltageUv, &socVoltageUv, &vddVoltageUv};
|
|
||||||
|
|
||||||
// Single regulator init/exit cycle
|
|
||||||
if (R_SUCCEEDED(rgltrInitialize())) [[likely]] {
|
|
||||||
if (IsMariko()) {
|
|
||||||
// Mariko with EOS: all 5 domains
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
|
||||||
RgltrSession session;
|
|
||||||
if (R_SUCCEEDED(rgltrOpenSession(&session, domains[i]))) [[likely]] {
|
|
||||||
if (R_FAILED(rgltrGetVoltage(&session, voltages[i]))) {
|
|
||||||
*voltages[i] = 0;
|
|
||||||
}
|
|
||||||
rgltrCloseSession(&session);
|
|
||||||
} else {
|
|
||||||
*voltages[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Erista
|
|
||||||
// Erista with EOS: CPU, GPU, SOC, VDD (no DRAM)
|
|
||||||
for (int i = 0; i < 5; ++i) {
|
|
||||||
if (i == 2) continue; // Skip DRAM domain
|
|
||||||
|
|
||||||
RgltrSession session;
|
|
||||||
if (R_SUCCEEDED(rgltrOpenSession(&session, domains[i]))) [[likely]] {
|
|
||||||
if (R_FAILED(rgltrGetVoltage(&session, voltages[i]))) {
|
|
||||||
*voltages[i] = 0;
|
|
||||||
}
|
|
||||||
rgltrCloseSession(&session);
|
|
||||||
} else {
|
|
||||||
*voltages[i] = 0;
|
|
||||||
}
|
|
||||||
emcVoltageUv = 0; // Erista never supports DRAM
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
rgltrExit();
|
|
||||||
} else {
|
|
||||||
// Zero all voltages on regulator failure
|
|
||||||
memset(&cpuVoltageUv, 0, sizeof(u32) * 5);
|
|
||||||
}
|
|
||||||
|
|
||||||
// === SYSCLK CONTEXT UPDATE ===
|
// === SYSCLK CONTEXT UPDATE ===
|
||||||
const Result rc = sysclkIpcGetCurrentContext(this->context);
|
const Result rc = sysclkIpcGetCurrentContext(this->context);
|
||||||
if (R_FAILED(rc)) [[unlikely]] {
|
if (R_FAILED(rc)) [[unlikely]] {
|
||||||
@@ -240,39 +177,37 @@ void BaseMenuGui::refresh()
|
|||||||
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
|
strcpy(displayStrings[1], sysclkFormatProfile(context->profile, true));
|
||||||
|
|
||||||
// Current frequencies
|
// Current frequencies
|
||||||
u32 hz = context->freqs[0]; // CPU
|
u32 hz = context->freqs[SysClkModule_CPU]; // CPU
|
||||||
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[2], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->freqs[1]; // GPU
|
hz = context->freqs[SysClkModule_GPU]; // GPU
|
||||||
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[3], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->freqs[2]; // MEM
|
hz = context->freqs[SysClkModule_MEM]; // MEM
|
||||||
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[4], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
// Real frequencies
|
// Real frequencies
|
||||||
hz = context->realFreqs[0]; // CPU
|
hz = context->realFreqs[SysClkModule_CPU]; // CPU
|
||||||
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[5], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->realFreqs[1]; // GPU
|
hz = context->realFreqs[SysClkModule_GPU]; // GPU
|
||||||
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[6], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
hz = context->realFreqs[2]; // MEM
|
hz = context->realFreqs[SysClkModule_MEM]; // MEM
|
||||||
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
sprintf(displayStrings[7], "%u.%u MHz", hz / 1000000U, (hz / 100000U) % 10U);
|
||||||
|
|
||||||
// Voltages
|
// Voltages
|
||||||
sprintf(displayStrings[8], "%.1f mV", cpuVoltageUv / 1000.0);
|
sprintf(displayStrings[8], "%.1f mV", context->voltages[HocClkVoltage_CPU] / 1000.0);
|
||||||
sprintf(displayStrings[9], "%.1f mV", gpuVoltageUv / 1000.0);
|
sprintf(displayStrings[9], "%.1f mV", context->voltages[HocClkVoltage_GPU] / 1000.0);
|
||||||
|
|
||||||
// Memory voltage (handle VDD case)
|
// Memory voltage (handle VDD case)
|
||||||
if (emcVoltageUv && vddVoltageUv) {
|
if (IsMariko()) {
|
||||||
//sprintf(displayStrings[10], "%u%u mV", vddVoltageUv / 1000U, emcVoltageUv / 1000U);
|
//sprintf(displayStrings[10], "%u%u mV", vddVoltageUv / 1000U, emcVoltageUv / 1000U);
|
||||||
//sprintf(displayStrings[10], "%u%.1f mV", vddVoltageUv / 1000U, emcVoltageUv / 1000.0f);
|
//sprintf(displayStrings[10], "%u%.1f mV", vddVoltageUv / 1000U, emcVoltageUv / 1000.0f);
|
||||||
sprintf(displayStrings[10], "%u.%u%u mV", vddVoltageUv / 1000U, (vddVoltageUv % 1000U) / 100U, emcVoltageUv / 1000U);
|
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDDQ_MarikoOnly] / 1000U);
|
||||||
} else if (vddVoltageUv) {
|
} else {
|
||||||
//sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U);
|
//sprintf(displayStrings[10], "%u mV", vddVoltageUv / 1000U);
|
||||||
sprintf(displayStrings[10], "%u.%u mV", vddVoltageUv / 1000U, (vddVoltageUv % 1000U) / 100U);
|
sprintf(displayStrings[10], "%u.%u%u mV", context->voltages[HocClkVoltage_EMCVDD2] / 1000U, (context->voltages[HocClkVoltage_EMCVDD2] % 1000U) / 100U, context->voltages[HocClkVoltage_EMCVDD2] / 1000U);
|
||||||
} else if (emcVoltageUv) {
|
|
||||||
sprintf(displayStrings[10], "%u mV", emcVoltageUv / 1000U);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Temperatures and pre-compute colors
|
// Temperatures and pre-compute colors
|
||||||
@@ -289,13 +224,16 @@ void BaseMenuGui::refresh()
|
|||||||
tempColors[2] = tsl::GradientColor(millis * 0.001f);
|
tempColors[2] = tsl::GradientColor(millis * 0.001f);
|
||||||
|
|
||||||
// SOC voltage (if available)
|
// SOC voltage (if available)
|
||||||
if (socVoltageUv) {
|
sprintf(displayStrings[14], "%u mV", context->voltages[HocClkVoltage_SOC] / 1000U);
|
||||||
sprintf(displayStrings[14], "%u mV", socVoltageUv / 1000U);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Power
|
// Power
|
||||||
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
|
sprintf(displayStrings[15], "%d mW", context->power[0]); // Now
|
||||||
sprintf(displayStrings[16], "%d mW", context->power[1]); // Avg
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tsl::elm::Element* BaseMenuGui::baseUI()
|
tsl::elm::Element* BaseMenuGui::baseUI()
|
||||||
|
|||||||
@@ -36,11 +36,6 @@ class BaseMenuGui : public BaseGui
|
|||||||
protected:
|
protected:
|
||||||
SysClkContext* context;
|
SysClkContext* context;
|
||||||
std::uint64_t lastContextUpdate;
|
std::uint64_t lastContextUpdate;
|
||||||
std::uint32_t cpuVoltageUv;
|
|
||||||
std::uint32_t gpuVoltageUv;
|
|
||||||
std::uint32_t emcVoltageUv;
|
|
||||||
std::uint32_t socVoltageUv; //add soc voltage
|
|
||||||
std::uint32_t vddVoltageUv;//add vdd2 voltage
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
bool g_hardwareModelCached = false;
|
bool g_hardwareModelCached = false;
|
||||||
@@ -71,6 +66,6 @@ class BaseMenuGui : public BaseGui
|
|||||||
virtual void listUI() = 0;
|
virtual void listUI() = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
char displayStrings[17][32]; // Pre-formatted display strings
|
char displayStrings[32][32]; // Pre-formatted display strings
|
||||||
tsl::Color tempColors[3]; // Pre-computed temperature colors
|
tsl::Color tempColors[3]; // Pre-computed temperature colors
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -28,13 +28,39 @@
|
|||||||
#include <nxExt.h>
|
#include <nxExt.h>
|
||||||
#include "board.h"
|
#include "board.h"
|
||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
|
#include "rgltr.h"
|
||||||
|
#include "file_utils.h"
|
||||||
|
#include <algorithm> // for std::clamp
|
||||||
|
#include <math.h>
|
||||||
|
#include <numeric>
|
||||||
|
|
||||||
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
|
#define HOSSVC_HAS_CLKRST (hosversionAtLeast(8,0,0))
|
||||||
#define HOSSVC_HAS_TC (hosversionAtLeast(5,0,0))
|
#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 (1000'000ULL)
|
||||||
|
|
||||||
|
Result nvCheck = 1;
|
||||||
|
|
||||||
|
Thread gpuLThread;
|
||||||
|
Thread cpuCore0Thread;
|
||||||
|
Thread cpuCore1Thread;
|
||||||
|
Thread cpuCore2Thread;
|
||||||
|
Thread cpuCore3Thread;
|
||||||
|
|
||||||
|
uint32_t GPU_Load_u = 0, fd = 0;
|
||||||
|
|
||||||
static SysClkSocType g_socType = SysClkSocType_Erista;
|
static SysClkSocType g_socType = SysClkSocType_Erista;
|
||||||
static HorizonOCConsoleType g_consoleType = HorizonOCConsoleType_Unknown;
|
static HorizonOCConsoleType g_consoleType = HorizonOCConsoleType_Unknown;
|
||||||
|
|
||||||
|
uint64_t idletick0 = systemtickfrequency;
|
||||||
|
uint64_t idletick1 = systemtickfrequency;
|
||||||
|
uint64_t idletick2 = systemtickfrequency;
|
||||||
|
uint64_t idletick3 = systemtickfrequency;
|
||||||
|
u32 cpu0, cpu1, cpu2, cpu3, cpuAvg;
|
||||||
|
|
||||||
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
const char* Board::GetModuleName(SysClkModule module, bool pretty)
|
||||||
{
|
{
|
||||||
ASSERT_ENUM_VALID(SysClkModule, module);
|
ASSERT_ENUM_VALID(SysClkModule, module);
|
||||||
@@ -85,6 +111,65 @@ PcvModuleId Board::GetPcvModuleId(SysClkModule sysclkModule)
|
|||||||
return pcvModuleId;
|
return pcvModuleId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CheckCore0(void*) {
|
||||||
|
while(true) {
|
||||||
|
uint64_t idletick_a0 = 0;
|
||||||
|
uint64_t idletick_b0 = 0;
|
||||||
|
svcGetInfo(&idletick_b0, InfoType_IdleTickCount, INVALID_HANDLE, 0);
|
||||||
|
svcSleepThread(CPU_TICK_WAIT);
|
||||||
|
svcGetInfo(&idletick_a0, InfoType_IdleTickCount, INVALID_HANDLE, 0);
|
||||||
|
idletick0 = idletick_a0 - idletick_b0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckCore1(void*) {
|
||||||
|
while(true) {
|
||||||
|
uint64_t idletick_a1 = 0;
|
||||||
|
uint64_t idletick_b1 = 0;
|
||||||
|
svcGetInfo(&idletick_b1, InfoType_IdleTickCount, INVALID_HANDLE, 1);
|
||||||
|
svcSleepThread(CPU_TICK_WAIT);
|
||||||
|
svcGetInfo(&idletick_a1, InfoType_IdleTickCount, INVALID_HANDLE, 1);
|
||||||
|
idletick1 = idletick_a1 - idletick_b1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckCore2(void*) {
|
||||||
|
while(true) {
|
||||||
|
uint64_t idletick_a2 = 0;
|
||||||
|
uint64_t idletick_b2 = 0;
|
||||||
|
svcGetInfo(&idletick_b2, InfoType_IdleTickCount, INVALID_HANDLE, 2);
|
||||||
|
svcSleepThread(CPU_TICK_WAIT);
|
||||||
|
svcGetInfo(&idletick_a2, InfoType_IdleTickCount, INVALID_HANDLE, 2);
|
||||||
|
idletick2 = idletick_a2 - idletick_b2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CheckCore3(void*) {
|
||||||
|
while(true) {
|
||||||
|
uint64_t idletick_a3 = 0;
|
||||||
|
uint64_t idletick_b3 = 0;
|
||||||
|
svcGetInfo(&idletick_b3, InfoType_IdleTickCount, INVALID_HANDLE, 3);
|
||||||
|
svcSleepThread(CPU_TICK_WAIT);
|
||||||
|
svcGetInfo(&idletick_a3, InfoType_IdleTickCount, INVALID_HANDLE, 3);
|
||||||
|
idletick3 = idletick_a3 - idletick_b3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void gpuLoadThread(void*) {
|
||||||
|
#define gpu_samples_average 8
|
||||||
|
uint32_t gpu_load_array[gpu_samples_average] = {0};
|
||||||
|
size_t i = 0;
|
||||||
|
if (R_SUCCEEDED(nvCheck)) do {
|
||||||
|
u32 temp;
|
||||||
|
if (R_SUCCEEDED(nvIoctl(fd, NVGPU_GPU_IOCTL_PMU_GET_GPU_LOAD, &temp))) {
|
||||||
|
gpu_load_array[i++ % gpu_samples_average] = temp;
|
||||||
|
GPU_Load_u = std::accumulate(&gpu_load_array[0], &gpu_load_array[gpu_samples_average], 0) / gpu_samples_average;
|
||||||
|
}
|
||||||
|
svcSleepThread(16'666'000); // wait a bit (this is the perfect amount of time to keep the reading accurate)
|
||||||
|
} while(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Initialize()
|
void Board::Initialize()
|
||||||
{
|
{
|
||||||
Result rc = 0;
|
Result rc = 0;
|
||||||
@@ -118,6 +203,24 @@ void Board::Initialize()
|
|||||||
rc = tmp451Initialize();
|
rc = tmp451Initialize();
|
||||||
ASSERT_RESULT_OK(rc, "tmp451Initialize");
|
ASSERT_RESULT_OK(rc, "tmp451Initialize");
|
||||||
|
|
||||||
|
if (R_SUCCEEDED(nvInitialize())) nvCheck = nvOpen(&fd, "/dev/nvhost-ctrl-gpu");
|
||||||
|
|
||||||
|
threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2);
|
||||||
|
threadStart(&gpuLThread);
|
||||||
|
|
||||||
|
threadCreate(&cpuCore0Thread, CheckCore0, NULL, NULL, 0x1000, 0x10, 0);
|
||||||
|
threadStart(&cpuCore0Thread);
|
||||||
|
|
||||||
|
threadCreate(&cpuCore1Thread, CheckCore1, NULL, NULL, 0x1000, 0x10, 1);
|
||||||
|
threadStart(&cpuCore1Thread);
|
||||||
|
|
||||||
|
threadCreate(&cpuCore2Thread, CheckCore2, NULL, NULL, 0x1000, 0x10, 2);
|
||||||
|
threadStart(&cpuCore2Thread);
|
||||||
|
|
||||||
|
threadCreate(&cpuCore3Thread, CheckCore3, NULL, NULL, 0x1000, 0x10, 3);
|
||||||
|
threadStart(&cpuCore3Thread);
|
||||||
|
|
||||||
|
|
||||||
FetchHardwareInfos();
|
FetchHardwareInfos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,6 +245,13 @@ void Board::Exit()
|
|||||||
|
|
||||||
max17050Exit();
|
max17050Exit();
|
||||||
tmp451Exit();
|
tmp451Exit();
|
||||||
|
|
||||||
|
threadClose(&gpuLThread);
|
||||||
|
threadClose(&cpuCore0Thread);
|
||||||
|
threadClose(&cpuCore1Thread);
|
||||||
|
threadClose(&cpuCore2Thread);
|
||||||
|
threadClose(&cpuCore3Thread);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SysClkProfile Board::GetProfile()
|
SysClkProfile Board::GetProfile()
|
||||||
@@ -464,21 +574,26 @@ std::int32_t Board::GetPowerMw(SysClkPowerSensor sensor)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::uint32_t Board::GetRamLoad(SysClkRamLoad loadSource)
|
std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
||||||
{
|
{
|
||||||
switch(loadSource)
|
switch(loadSource)
|
||||||
{
|
{
|
||||||
case SysClkRamLoad_All:
|
case SysClkPartLoad_EMC:
|
||||||
return t210EmcLoadAll();
|
return t210EmcLoadAll();
|
||||||
case SysClkRamLoad_Cpu:
|
case SysClkPartLoad_EMCCpu:
|
||||||
return t210EmcLoadCpu();
|
return t210EmcLoadCpu();
|
||||||
|
case HocClkPartLoad_GPU:
|
||||||
|
return GPU_Load_u;
|
||||||
|
case HocClkPartLoad_CPUAvg:
|
||||||
|
return (idletick0 + idletick1 + idletick2 + idletick3) / 4;
|
||||||
default:
|
default:
|
||||||
ASSERT_ENUM_VALID(SysClkRamLoad, loadSource);
|
ASSERT_ENUM_VALID(SysClkPartLoad, loadSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
SysClkSocType Board::GetSocType() {
|
SysClkSocType Board::GetSocType() {
|
||||||
return g_socType;
|
return g_socType;
|
||||||
}
|
}
|
||||||
@@ -500,12 +615,108 @@ void Board::FetchHardwareInfos()
|
|||||||
|
|
||||||
switch(sku)
|
switch(sku)
|
||||||
{
|
{
|
||||||
case 2 .. 5:
|
case 2:
|
||||||
|
case 3:
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
g_socType = SysClkSocType_Mariko;
|
g_socType = SysClkSocType_Mariko;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_socType = SysClkSocType_Erista;
|
g_socType = SysClkSocType_Erista;
|
||||||
}
|
}
|
||||||
|
|
||||||
g_consoleType = sku;
|
g_consoleType = (HorizonOCConsoleType)sku;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch Power domains (max77620):
|
||||||
|
* Name | Usage | uV step | uV min | uV default | uV max | Init
|
||||||
|
*-------+---------------+---------+--------+------------+---------+------------------
|
||||||
|
* sd0 | SoC | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
|
||||||
|
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
|
||||||
|
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
|
||||||
|
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
|
||||||
|
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
|
||||||
|
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||||
|
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
|
||||||
|
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
||||||
|
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
|
||||||
|
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||||
|
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
|
||||||
|
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||||
|
* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PcvPowerDomainId_Max77620_Sd0 = 0x3A000080,
|
||||||
|
PcvPowerDomainId_Max77620_Sd1 = 0x3A000081, // vdd2
|
||||||
|
PcvPowerDomainId_Max77620_Sd2 = 0x3A000082,
|
||||||
|
PcvPowerDomainId_Max77620_Sd3 = 0x3A000083,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo0 = 0x3A0000A0,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo1 = 0x3A0000A1,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo2 = 0x3A0000A2,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo3 = 0x3A0000A3,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo4 = 0x3A0000A4,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo5 = 0x3A0000A5,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo6 = 0x3A0000A6,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo7 = 0x3A0000A7,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo8 = 0x3A0000A8,
|
||||||
|
PcvPowerDomainId_Max77621_Cpu = 0x3A000003,
|
||||||
|
PcvPowerDomainId_Max77621_Gpu = 0x3A000004,
|
||||||
|
PcvPowerDomainId_Max77812_Cpu = 0x3A000003,
|
||||||
|
PcvPowerDomainId_Max77812_Gpu = 0x3A000004,
|
||||||
|
PcvPowerDomainId_Max77812_Dram = 0x3A000005, // vddq
|
||||||
|
} PowerDomainId;
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
|
||||||
|
{
|
||||||
|
RgltrSession session;
|
||||||
|
Result rc = 0;
|
||||||
|
u32 out;
|
||||||
|
switch(voltage)
|
||||||
|
{
|
||||||
|
case HocClkVoltage_SOC:
|
||||||
|
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd0);
|
||||||
|
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
|
||||||
|
rgltrGetVoltage(&session, &out);
|
||||||
|
rgltrCloseSession(&session);
|
||||||
|
break;
|
||||||
|
case HocClkVoltage_EMCVDD2:
|
||||||
|
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Sd1);
|
||||||
|
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
|
||||||
|
rgltrGetVoltage(&session, &out);
|
||||||
|
rgltrCloseSession(&session);
|
||||||
|
break;
|
||||||
|
case HocClkVoltage_CPU:
|
||||||
|
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Cpu);
|
||||||
|
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
|
||||||
|
rgltrGetVoltage(&session, &out);
|
||||||
|
rgltrCloseSession(&session);
|
||||||
|
break;
|
||||||
|
case HocClkVoltage_GPU:
|
||||||
|
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77621_Gpu);
|
||||||
|
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
|
||||||
|
rgltrGetVoltage(&session, &out);
|
||||||
|
rgltrCloseSession(&session);
|
||||||
|
break;
|
||||||
|
case HocClkVoltage_EMCVDDQ_MarikoOnly:
|
||||||
|
if(Board::GetSocType() == SysClkSocType_Mariko) {
|
||||||
|
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77812_Dram);
|
||||||
|
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
|
||||||
|
rgltrGetVoltage(&session, &out);
|
||||||
|
rgltrCloseSession(&session);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case HocClkVoltage_Display:
|
||||||
|
rc = rgltrOpenSession(&session, PcvPowerDomainId_Max77620_Ldo0);
|
||||||
|
ASSERT_RESULT_OK(rc, "rgltrOpenSession")
|
||||||
|
rgltrGetVoltage(&session, &out);
|
||||||
|
rgltrCloseSession(&session);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT_ENUM_VALID(HocClkVoltage, voltage);
|
||||||
|
}
|
||||||
|
|
||||||
|
return out > 0 ? out : 0;
|
||||||
|
}
|
||||||
|
|||||||
@@ -51,9 +51,10 @@ class Board
|
|||||||
static void GetFreqList(SysClkModule module, std::uint32_t* outList, std::uint32_t maxCount, std::uint32_t* outCount);
|
static void GetFreqList(SysClkModule module, std::uint32_t* outList, std::uint32_t maxCount, std::uint32_t* outCount);
|
||||||
static std::uint32_t GetTemperatureMilli(SysClkThermalSensor sensor);
|
static std::uint32_t GetTemperatureMilli(SysClkThermalSensor sensor);
|
||||||
static std::int32_t GetPowerMw(SysClkPowerSensor sensor);
|
static std::int32_t GetPowerMw(SysClkPowerSensor sensor);
|
||||||
static std::uint32_t GetRamLoad(SysClkRamLoad load);
|
static std::uint32_t GetPartLoad(SysClkPartLoad load);
|
||||||
static SysClkSocType GetSocType();
|
static SysClkSocType GetSocType();
|
||||||
static HorizonOCConsoleType GetConsoleType();
|
static HorizonOCConsoleType GetConsoleType();
|
||||||
|
static std::uint32_t GetVoltage(HocClkVoltage voltage);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static void FetchHardwareInfos();
|
static void FetchHardwareInfos();
|
||||||
|
|||||||
@@ -227,6 +227,8 @@ void ClockManager::RefreshFreqTableRow(SysClkModule module)
|
|||||||
void ClockManager::Tick()
|
void ClockManager::Tick()
|
||||||
{
|
{
|
||||||
std::scoped_lock lock{this->contextMutex};
|
std::scoped_lock lock{this->contextMutex};
|
||||||
|
AppletOperationMode opMode = appletGetOperationMode();
|
||||||
|
|
||||||
if(this->config->GetConfigValue(HocClkConfigValue_HandheldTDP) && opMode == AppletOperationMode_Handheld) {
|
if(this->config->GetConfigValue(HocClkConfigValue_HandheldTDP) && opMode == AppletOperationMode_Handheld) {
|
||||||
if(Board::GetConsoleType() == HorizonOCConsoleType_Lite) {
|
if(Board::GetConsoleType() == HorizonOCConsoleType_Lite) {
|
||||||
if(Board::GetPowerMw(SysClkPowerSensor_Now) < -(int)this->config->GetConfigValue(HocClkConfigValue_LiteTDPLimit)) {
|
if(Board::GetPowerMw(SysClkPowerSensor_Now) < -(int)this->config->GetConfigValue(HocClkConfigValue_LiteTDPLimit)) {
|
||||||
@@ -254,7 +256,6 @@ void ClockManager::Tick()
|
|||||||
std::uint32_t nearestHz = 0;
|
std::uint32_t nearestHz = 0;
|
||||||
std::uint32_t mode = 0;
|
std::uint32_t mode = 0;
|
||||||
|
|
||||||
AppletOperationMode opMode = appletGetOperationMode();
|
|
||||||
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
Result rc = apmExtGetCurrentPerformanceConfiguration(&mode);
|
||||||
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
ASSERT_RESULT_OK(rc, "apmExtGetCurrentPerformanceConfiguration");
|
||||||
|
|
||||||
@@ -427,9 +428,14 @@ bool ClockManager::RefreshContext()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ram load do not and should not force a refresh, hasChanged untouched
|
// ram load do not and should not force a refresh, hasChanged untouched
|
||||||
for (unsigned int loadSource = 0; loadSource < SysClkRamLoad_EnumMax; loadSource++)
|
for (unsigned int loadSource = 0; loadSource < SysClkPartLoad_EnumMax; loadSource++)
|
||||||
{
|
{
|
||||||
this->context->ramLoad[loadSource] = Board::GetRamLoad((SysClkRamLoad)loadSource);
|
this->context->PartLoad[loadSource] = Board::GetPartLoad((SysClkPartLoad)loadSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (unsigned int voltageSource = 0; voltageSource < HocClkVoltage_EnumMax; voltageSource++)
|
||||||
|
{
|
||||||
|
this->context->voltages[voltageSource] = Board::GetVoltage((HocClkVoltage)voltageSource);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this->ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &this->lastCsvWriteNs))
|
if (this->ConfigIntervalTimeout(SysClkConfigValue_CsvWriteIntervalMs, ns, &this->lastCsvWriteNs))
|
||||||
|
|||||||
@@ -47,9 +47,11 @@ extern "C"
|
|||||||
std::uint32_t __nx_applet_type = AppletType_None;
|
std::uint32_t __nx_applet_type = AppletType_None;
|
||||||
TimeServiceType __nx_time_service_type = TimeServiceType_System;
|
TimeServiceType __nx_time_service_type = TimeServiceType_System;
|
||||||
std::uint32_t __nx_fs_num_sessions = 1;
|
std::uint32_t __nx_fs_num_sessions = 1;
|
||||||
|
u32 __nx_nv_transfermem_size = 0x8000;
|
||||||
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
size_t nx_inner_heap_size = INNER_HEAP_SIZE;
|
||||||
char nx_inner_heap[INNER_HEAP_SIZE];
|
char nx_inner_heap[INNER_HEAP_SIZE];
|
||||||
|
NvServiceType __nx_nv_service_type = NvServiceType_Factory;
|
||||||
|
|
||||||
|
|
||||||
void __libnx_initheap(void)
|
void __libnx_initheap(void)
|
||||||
{
|
{
|
||||||
|
|||||||
27
Source/sys-clk/sysmodule/src/notification.h
Normal file
27
Source/sys-clk/sysmodule/src/notification.h
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <ctime>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
static void writeNotification(const std::string& message) {
|
||||||
|
const char* flagPath = "sdmc:/config/ultrahand/flags/NOTIFICATIONS.flag";
|
||||||
|
|
||||||
|
FILE* flagFile = fopen(flagPath, "r");
|
||||||
|
if (!flagFile) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fclose(flagFile);
|
||||||
|
|
||||||
|
std::string filename = "Horizon OC -" + std::to_string(std::time(nullptr)) + ".notify";
|
||||||
|
std::string fullPath = "sdmc:/config/ultrahand/notifications/" + filename;
|
||||||
|
|
||||||
|
FILE* file = fopen(fullPath.c_str(), "w");
|
||||||
|
if (file) {
|
||||||
|
fprintf(file, "{\n");
|
||||||
|
fprintf(file, " \"text\": \"%s\",\n", message.c_str());
|
||||||
|
fprintf(file, " \"fontSize\": 28\n");
|
||||||
|
fprintf(file, "}\n");
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
95
Source/sys-clk/sysmodule/src/pcv_types.h
Normal file
95
Source/sys-clk/sysmodule/src/pcv_types.h
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#pragma once
|
||||||
|
/*
|
||||||
|
* SDx actual min is 625 mV. Multipliers 0/1 reserved.
|
||||||
|
* SD0 max is 1400 mV
|
||||||
|
* SD1 max is 1550 mV
|
||||||
|
* SD2 max is 3787.5 mV
|
||||||
|
* SD3 max is 3787.5 mV
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Switch Power domains (max77620):
|
||||||
|
* Name | Usage | uV step | uV min | uV default | uV max | Init
|
||||||
|
*-------+---------------+---------+--------+------------+---------+------------------
|
||||||
|
* sd0 | SoC | 12500 | 600000 | 625000 | 1400000 | 1.125V (pkg1.1)
|
||||||
|
* sd1 | SDRAM | 12500 | 600000 | 1125000 | 1125000 | 1.1V (pkg1.1)
|
||||||
|
* sd2 | ldo{0-1, 7-8} | 12500 | 600000 | 1325000 | 1350000 | 1.325V (pcv)
|
||||||
|
* sd3 | 1.8V general | 12500 | 600000 | 1800000 | 1800000 |
|
||||||
|
* ldo0 | Display Panel | 25000 | 800000 | 1200000 | 1200000 | 1.2V (pkg1.1)
|
||||||
|
* ldo1 | XUSB, PCIE | 25000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||||
|
* ldo2 | SDMMC1 | 50000 | 800000 | 1800000 | 3300000 |
|
||||||
|
* ldo3 | GC ASIC | 50000 | 800000 | 3100000 | 3100000 | 3.1V (pcv)
|
||||||
|
* ldo4 | RTC | 12500 | 800000 | 850000 | 850000 | 0.85V (AO, pcv)
|
||||||
|
* ldo5 | GC Card | 50000 | 800000 | 1800000 | 1800000 | 1.8V (pcv)
|
||||||
|
* ldo6 | Touch, ALS | 50000 | 800000 | 2900000 | 2900000 | 2.9V (pcv)
|
||||||
|
* ldo7 | XUSB | 50000 | 800000 | 1050000 | 1050000 | 1.05V (pcv)
|
||||||
|
* ldo8 | XUSB, DP, MCU | 50000 | 800000 | 1050000 | 2800000 | 1.05V/2.8V (pcv)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
// GPIOs T210: 3: 3.3V, 5: CPU PMIC, 6: GPU PMIC, 7: DSI/VI 1.2V powered by ldo0.
|
||||||
|
|
||||||
|
/*
|
||||||
|
* OTP: T210 - T210B01:
|
||||||
|
* SD0: 1.0V 1.05V - SoC. EN Based on FPSSRC.
|
||||||
|
* SD1: 1.15V 1.1V - DRAM for T210. EN Based on FPSSRC.
|
||||||
|
* SD2: 1.35V 1.35V
|
||||||
|
* SD3: 1.8V 1.8V
|
||||||
|
* All powered off?
|
||||||
|
* LDO0: -- -- - Display
|
||||||
|
* LDO1: 1.05V 1.05V
|
||||||
|
* LDO2: -- -- - SD
|
||||||
|
* LDO3: 3.1V 3.1V - GC ASIC
|
||||||
|
* LDO4: 1.0V 0.8V - Needed for RTC domain on T210.
|
||||||
|
* LDO5: 3.1V 3.1V
|
||||||
|
* LDO6: 2.8V 2.9V - Touch.
|
||||||
|
* LDO7: 1.05V 1.0V
|
||||||
|
* LDO8: 1.05V 1.0V
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* MAX77620_AME_GPIO: control GPIO modes (bits 0 - 7 correspond to GPIO0 - GPIO7); 0 -> GPIO, 1 -> alt-mode
|
||||||
|
* MAX77620_REG_GPIOx: 0x9 sets output and enable
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PcvPowerDomain_Max77620_Sd0 = 0,
|
||||||
|
PcvPowerDomain_Max77620_Sd1 = 1,
|
||||||
|
PcvPowerDomain_Max77620_Sd2 = 2,
|
||||||
|
PcvPowerDomain_Max77620_Sd3 = 3,
|
||||||
|
PcvPowerDomain_Max77620_Ldo0 = 4,
|
||||||
|
PcvPowerDomain_Max77620_Ldo1 = 5,
|
||||||
|
PcvPowerDomain_Max77620_Ldo2 = 6,
|
||||||
|
PcvPowerDomain_Max77620_Ldo3 = 7,
|
||||||
|
PcvPowerDomain_Max77620_Ldo4 = 8,
|
||||||
|
PcvPowerDomain_Max77620_Ldo5 = 9,
|
||||||
|
PcvPowerDomain_Max77620_Ldo6 = 10,
|
||||||
|
PcvPowerDomain_Max77620_Ldo7 = 11,
|
||||||
|
PcvPowerDomain_Max77620_Ldo8 = 12,
|
||||||
|
PcvPowerDomain_Max77621_Cpu = 13,
|
||||||
|
PcvPowerDomain_Max77621_Gpu = 14,
|
||||||
|
PcvPowerDomain_Max77812_Cpu = 15,
|
||||||
|
PcvPowerDomain_Max77812_Gpu = 16,
|
||||||
|
PcvPowerDomain_Max77812_Dram = 17,
|
||||||
|
} PowerDomain;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PcvPowerDomainId_Max77620_Sd0 = 0x3A000080,
|
||||||
|
PcvPowerDomainId_Max77620_Sd1 = 0x3A000081, // vdd2
|
||||||
|
PcvPowerDomainId_Max77620_Sd2 = 0x3A000082,
|
||||||
|
PcvPowerDomainId_Max77620_Sd3 = 0x3A000083,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo0 = 0x3A0000A0,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo1 = 0x3A0000A1,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo2 = 0x3A0000A2,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo3 = 0x3A0000A3,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo4 = 0x3A0000A4,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo5 = 0x3A0000A5,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo6 = 0x3A0000A6,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo7 = 0x3A0000A7,
|
||||||
|
PcvPowerDomainId_Max77620_Ldo8 = 0x3A0000A8,
|
||||||
|
PcvPowerDomainId_Max77621_Cpu = 0x3A000003,
|
||||||
|
PcvPowerDomainId_Max77621_Gpu = 0x3A000004,
|
||||||
|
PcvPowerDomainId_Max77812_Cpu = 0x3A000003,
|
||||||
|
PcvPowerDomainId_Max77812_Gpu = 0x3A000004,
|
||||||
|
PcvPowerDomainId_Max77812_Dram = 0x3A000005, // vddq
|
||||||
|
} PowerDomainId;
|
||||||
19
Source/sys-clk/sysmodule/src/rgltr.h
Normal file
19
Source/sys-clk/sysmodule/src/rgltr.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
#pragma once
|
||||||
|
#include <switch.h>
|
||||||
|
#include "pcv_types.h"
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Service s;
|
||||||
|
} RgltrSession;
|
||||||
|
|
||||||
|
Result rgltrInitialize(void);
|
||||||
|
|
||||||
|
void rgltrExit(void);
|
||||||
|
|
||||||
|
Service* rgltrGetServiceSession(void);
|
||||||
|
|
||||||
|
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id);
|
||||||
|
void rgltrCloseSession(RgltrSession* session);
|
||||||
|
Result rgltrGetVoltage(RgltrSession* session, u32 *out_volt);
|
||||||
|
Result rgltrGetPowerModuleNumLimit(u32 *out);
|
||||||
|
Result rgltrGetVoltageEnabled(RgltrSession* session, u32 *out);
|
||||||
41
Source/sys-clk/sysmodule/src/rgltr_services.cpp
Normal file
41
Source/sys-clk/sysmodule/src/rgltr_services.cpp
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
#include <switch.h>
|
||||||
|
#include "rgltr.h"
|
||||||
|
#include "rgltr_services.h" // for extern Service g_rgltrSrv, etc.
|
||||||
|
|
||||||
|
// Global service handle
|
||||||
|
Service g_rgltrSrv;
|
||||||
|
|
||||||
|
Result rgltrInitialize(void) {
|
||||||
|
if (hosversionBefore(8, 0, 0)) {
|
||||||
|
return MAKERESULT(Module_Libnx, LibnxError_IncompatSysVer);
|
||||||
|
}
|
||||||
|
return smGetService(&g_rgltrSrv, "rgltr");
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgltrExit(void) {
|
||||||
|
serviceClose(&g_rgltrSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id) {
|
||||||
|
const u32 in = (u32)module_id;
|
||||||
|
return serviceDispatchIn(
|
||||||
|
&g_rgltrSrv,
|
||||||
|
0,
|
||||||
|
in,
|
||||||
|
.out_num_objects = 1,
|
||||||
|
.out_objects = &session_out->s
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result rgltrGetVoltage(RgltrSession* session, u32* out_volt) {
|
||||||
|
u32 temp = 0;
|
||||||
|
Result rc = serviceDispatchOut(&session->s, 4, temp);
|
||||||
|
if (R_SUCCEEDED(rc)) {
|
||||||
|
*out_volt = temp;
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void rgltrCloseSession(RgltrSession* session) {
|
||||||
|
serviceClose(&session->s);
|
||||||
|
}
|
||||||
15
Source/sys-clk/sysmodule/src/rgltr_services.h
Normal file
15
Source/sys-clk/sysmodule/src/rgltr_services.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <switch.h> // for Service, Result, hosversionBefore(), smGetService(), serviceClose(), etc.
|
||||||
|
#include "rgltr.h" // for RgltrSession, PowerDomainId, etc.
|
||||||
|
|
||||||
|
extern Service g_rgltrSrv;
|
||||||
|
|
||||||
|
Result rgltrInitialize(void);
|
||||||
|
void rgltrExit(void);
|
||||||
|
|
||||||
|
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id);
|
||||||
|
|
||||||
|
Result rgltrGetVoltage(RgltrSession* session, u32* out_volt);
|
||||||
|
|
||||||
|
void rgltrCloseSession(RgltrSession* session);
|
||||||
Reference in New Issue
Block a user