sysclk: code cleanup and fan speed
also fix incompatibility with nx fancontrol
This commit is contained in:
@@ -1,163 +1,4 @@
|
|||||||
# sys-clk
|
# hoc-clk
|
||||||
|
|
||||||
Switch sysmodule allowing you to set cpu/gpu/mem clocks according to the running application and docked state.
|
Switch sysmodule allowing you to set cpu/gpu/mem clocks according to the running application and docked state.
|
||||||
|
Modified for Horizon OC
|
||||||
## Installation
|
|
||||||
|
|
||||||
The following instructions assumes you have a Nintendo Switch running Atmosphère, updated to at least the latest stable version.
|
|
||||||
Copy the `atmosphere`, and `switch` folders at the root of your sdcard, overwriting files if prompted. Also copy the `config` folder if you're not updating, to include default settings.
|
|
||||||
|
|
||||||
**Note:** sys-clk-overlay requires to have [Tesla](https://gbatemp.net/threads/tesla-the-nintendo-switch-overlay-menu.557362/) installed and running
|
|
||||||
|
|
||||||
## Relevant files
|
|
||||||
|
|
||||||
* Config file allows one to set custom clocks per docked state and title id, described below
|
|
||||||
|
|
||||||
`/config/sys-clk/config.ini`
|
|
||||||
|
|
||||||
* Log file where the logs are written if enabled
|
|
||||||
|
|
||||||
`/config/sys-clk/log.txt`
|
|
||||||
|
|
||||||
* Log flag file enables log writing if file exists
|
|
||||||
|
|
||||||
`/config/sys-clk/log.flag`
|
|
||||||
|
|
||||||
* CSV file where the title id, profile, clocks and temperatures are written if enabled
|
|
||||||
|
|
||||||
`/config/sys-clk/context.csv`
|
|
||||||
|
|
||||||
* sys-clk manager app (accessible from the hbmenu)
|
|
||||||
|
|
||||||
`/switch/sys-clk-manager.nro`
|
|
||||||
|
|
||||||
* sys-clk overlay (accessible from anywhere by invoking the [Tesla menu](https://gbatemp.net/threads/tesla-the-nintendo-switch-overlay-menu.557362/))
|
|
||||||
|
|
||||||
`/switch/.overlays/sys-clk-overlay.ovl`
|
|
||||||
|
|
||||||
* sys-clk core sysmodule
|
|
||||||
|
|
||||||
`/atmosphere/contents/00FF0000636C6BFF/exefs.nsp`
|
|
||||||
`/atmosphere/contents/00FF0000636C6BFF/flags/boot2.flag`
|
|
||||||
|
|
||||||
## Config
|
|
||||||
|
|
||||||
Presets can be customized by adding them to the ini config file located at `/config/sys-clk/config.ini`, using the following template for each app
|
|
||||||
|
|
||||||
```
|
|
||||||
[Application Title ID]
|
|
||||||
docked_cpu=
|
|
||||||
docked_gpu=
|
|
||||||
docked_mem=
|
|
||||||
handheld_charging_cpu=
|
|
||||||
handheld_charging_gpu=
|
|
||||||
handheld_charging_mem=
|
|
||||||
handheld_charging_usb_cpu=
|
|
||||||
handheld_charging_usb_gpu=
|
|
||||||
handheld_charging_usb_mem=
|
|
||||||
handheld_charging_official_cpu=
|
|
||||||
handheld_charging_official_gpu=
|
|
||||||
handheld_charging_official_mem=
|
|
||||||
handheld_cpu=
|
|
||||||
handheld_gpu=
|
|
||||||
handheld_mem=
|
|
||||||
```
|
|
||||||
|
|
||||||
* Replace `Application Title ID` with the title id of the game/application you're interested in customizing.
|
|
||||||
A list of games title id can be found in the [Switchbrew wiki](https://switchbrew.org/wiki/Title_list/Games).
|
|
||||||
* Frequencies are expressed in mhz, and will be scaled to the nearest possible values, described in the clock table below.
|
|
||||||
* If any key is omitted, value is empty or set to 0, it will be ignored, and stock clocks will apply.
|
|
||||||
* If charging, sys-clk will look for the frequencies in that order, picking the first found
|
|
||||||
1. Charger specific config (USB or Official) `handheld_charging_usb_X` or `handheld_charging_official_X`
|
|
||||||
2. Non specific charging config `handheld_charging_X`
|
|
||||||
3. Handheld config `handheld_X`
|
|
||||||
|
|
||||||
### Example 1: Zelda BOTW
|
|
||||||
|
|
||||||
* Overclock CPU when docked or charging
|
|
||||||
* Overclock MEM to docked clocks when handheld
|
|
||||||
|
|
||||||
Leads to a smoother framerate overall (ex: in the korok forest)
|
|
||||||
|
|
||||||
```
|
|
||||||
[01007EF00011E000]
|
|
||||||
docked_cpu=1224
|
|
||||||
handheld_charging_cpu=1224
|
|
||||||
handheld_mem=1600
|
|
||||||
```
|
|
||||||
|
|
||||||
### Example 2: Picross
|
|
||||||
|
|
||||||
* Underclocks on handheld to save battery
|
|
||||||
|
|
||||||
```
|
|
||||||
[0100BA0003EEA000]
|
|
||||||
handheld_cpu=816
|
|
||||||
handheld_gpu=153
|
|
||||||
handheld_mem=800
|
|
||||||
```
|
|
||||||
|
|
||||||
### Advanced
|
|
||||||
|
|
||||||
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 |
|
|
||||||
|:-----------------------:|-------------------------------------------------------------------------------|:-------:|
|
|
||||||
|**temp_log_interval_ms** | Defines how often sys-clk logs temperatures, in milliseconds (`0` to disable) | 0 ms |
|
|
||||||
|**freq_log_interval_ms** | Defines how often sys-clk logs real freqs, in milliseconds (`0` to disable) | 0 ms |
|
|
||||||
|**power_log_interval_ms**| Defines how often sys-clk logs power usage, 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 | 300 ms |
|
|
||||||
|
|
||||||
|
|
||||||
## Capping
|
|
||||||
|
|
||||||
To protect the battery from excessive strain, clocks requested from config may be capped before applying, depending on your current profile:
|
|
||||||
|
|
||||||
| | Handheld | Charging (USB) | Charging (Official) | Docked |
|
|
||||||
|:-----:|:--------:|:--------------:|:-------------------:|:------:|
|
|
||||||
|**MEM**| - | - | - | - |
|
|
||||||
|**CPU**| - | - | - | - |
|
|
||||||
|**GPU**| 460 MHz* | 768 MHz | - | - |
|
|
||||||
*\* GPU handheld max for Mariko is increased to 614 MHz*
|
|
||||||
|
|
||||||
## Clock table (MHz)
|
|
||||||
|
|
||||||
### MEM clocks
|
|
||||||
* 1600 → official docked, boost mode, max clock
|
|
||||||
* 1331 → official handheld
|
|
||||||
* 1065
|
|
||||||
* 800
|
|
||||||
* 665
|
|
||||||
|
|
||||||
### CPU clocks
|
|
||||||
* 1785 → max clock, boost mode
|
|
||||||
* 1683
|
|
||||||
* 1581
|
|
||||||
* 1428
|
|
||||||
* 1326
|
|
||||||
* 1224 → sdev oc
|
|
||||||
* 1122
|
|
||||||
* 1020 → official docked & handheld
|
|
||||||
* 918
|
|
||||||
* 816
|
|
||||||
* 714
|
|
||||||
* 612
|
|
||||||
|
|
||||||
### GPU clocks
|
|
||||||
* 921 → max clock
|
|
||||||
* 844
|
|
||||||
* 768 → official docked
|
|
||||||
* 691
|
|
||||||
* 614
|
|
||||||
* 537
|
|
||||||
* 460 → max handheld
|
|
||||||
* 384 → official handheld
|
|
||||||
* 307 → official handheld
|
|
||||||
* 230
|
|
||||||
* 153
|
|
||||||
* 76 → boost mode
|
|
||||||
|
|
||||||
**Notes:**
|
|
||||||
1. GPU overclock is capped at 460MHz in handheld and capped at 768MHz if charging, unless you're using the PD Charger.
|
|
||||||
2. Clocks higher than 768MHz need the PD Charger is plugged in.
|
|
||||||
22
Source/sys-clk/common/include/pwm.h
Normal file
22
Source/sys-clk/common/include/pwm.h
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <switch.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
Service s;
|
||||||
|
} PwmChannelSession;
|
||||||
|
|
||||||
|
Result pwmInitialize(void);
|
||||||
|
void pwmExit(void);
|
||||||
|
Service* pwmGetServiceSession(void);
|
||||||
|
Result pwmOpenSession2(PwmChannelSession *out, u32 device_code);
|
||||||
|
Result pwmChannelSessionGetDutyCycle(PwmChannelSession *c, double* out);
|
||||||
|
void pwmChannelSessionClose(PwmChannelSession *c);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} // extern "C"
|
||||||
|
#endif
|
||||||
65
Source/sys-clk/common/include/service_guard.h
Normal file
65
Source/sys-clk/common/include/service_guard.h
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <switch/types.h>
|
||||||
|
#include <switch/result.h>
|
||||||
|
#include <switch/kernel/mutex.h>
|
||||||
|
#include <switch/sf/service.h>
|
||||||
|
#include <switch/services/sm.h>
|
||||||
|
|
||||||
|
typedef struct ServiceGuard {
|
||||||
|
Mutex mutex;
|
||||||
|
u32 refCount;
|
||||||
|
} ServiceGuard;
|
||||||
|
|
||||||
|
NX_INLINE bool serviceGuardBeginInit(ServiceGuard* g)
|
||||||
|
{
|
||||||
|
mutexLock(&g->mutex);
|
||||||
|
return (g->refCount++) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
NX_INLINE Result serviceGuardEndInit(ServiceGuard* g, Result rc, void (*cleanupFunc)(void))
|
||||||
|
{
|
||||||
|
if (R_FAILED(rc)) {
|
||||||
|
cleanupFunc();
|
||||||
|
--g->refCount;
|
||||||
|
}
|
||||||
|
mutexUnlock(&g->mutex);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
NX_INLINE void serviceGuardExit(ServiceGuard* g, void (*cleanupFunc)(void))
|
||||||
|
{
|
||||||
|
mutexLock(&g->mutex);
|
||||||
|
if (g->refCount && (--g->refCount) == 0)
|
||||||
|
cleanupFunc();
|
||||||
|
mutexUnlock(&g->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NX_GENERATE_SERVICE_GUARD_PARAMS(name, _paramdecl, _parampass) \
|
||||||
|
\
|
||||||
|
static ServiceGuard g_##name##Guard; \
|
||||||
|
NX_INLINE Result _##name##Initialize _paramdecl; \
|
||||||
|
static void _##name##Cleanup(void); \
|
||||||
|
\
|
||||||
|
Result name##Initialize _paramdecl \
|
||||||
|
{ \
|
||||||
|
Result rc = 0; \
|
||||||
|
if (serviceGuardBeginInit(&g_##name##Guard)) \
|
||||||
|
rc = _##name##Initialize _parampass; \
|
||||||
|
return serviceGuardEndInit(&g_##name##Guard, rc, _##name##Cleanup); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
void name##Exit(void) \
|
||||||
|
{ \
|
||||||
|
serviceGuardExit(&g_##name##Guard, _##name##Cleanup); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NX_GENERATE_SERVICE_GUARD(name) NX_GENERATE_SERVICE_GUARD_PARAMS(name, (void), ())
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -103,6 +103,7 @@ typedef enum
|
|||||||
HocClkPartLoad_GPU,
|
HocClkPartLoad_GPU,
|
||||||
HocClkPartLoad_CPUAvg,
|
HocClkPartLoad_CPUAvg,
|
||||||
HocClkPartLoad_BAT,
|
HocClkPartLoad_BAT,
|
||||||
|
HocClkPartLoad_FAN,
|
||||||
SysClkPartLoad_EnumMax
|
SysClkPartLoad_EnumMax
|
||||||
} SysClkPartLoad;
|
} SysClkPartLoad;
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
#include "i2c_reg.h"
|
#include "i2c.h"
|
||||||
|
|
||||||
Result I2cSet_U8(I2cDevice dev, u8 reg, u8 val) {
|
Result I2cSet_U8(I2cDevice dev, u8 reg, u8 val) {
|
||||||
// ams::fatal::srv::StopSoundTask::StopSound()
|
// ams::fatal::srv::StopSoundTask::StopSound()
|
||||||
35
Source/sys-clk/common/src/pwm.c
Normal file
35
Source/sys-clk/common/src/pwm.c
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
#define NX_SERVICE_ASSUME_NON_DOMAIN
|
||||||
|
#include <switch.h>
|
||||||
|
#include "service_guard.h"
|
||||||
|
#include "pwm.h"
|
||||||
|
|
||||||
|
static Service g_pwmSrv;
|
||||||
|
|
||||||
|
NX_GENERATE_SERVICE_GUARD(pwm);
|
||||||
|
|
||||||
|
Result _pwmInitialize(void) {
|
||||||
|
return smGetService(&g_pwmSrv, "pwm");
|
||||||
|
}
|
||||||
|
|
||||||
|
void _pwmCleanup(void) {
|
||||||
|
serviceClose(&g_pwmSrv);
|
||||||
|
}
|
||||||
|
|
||||||
|
Service* pwmGetServiceSession(void) {
|
||||||
|
return &g_pwmSrv;
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pwmOpenSession2(PwmChannelSession *out, u32 device_code) {
|
||||||
|
return serviceDispatchIn(&g_pwmSrv, 2, device_code,
|
||||||
|
.out_num_objects = 1,
|
||||||
|
.out_objects = &out->s,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result pwmChannelSessionGetDutyCycle(PwmChannelSession *c, double* out) {
|
||||||
|
return serviceDispatchOut(&c->s, 7, *out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pwmChannelSessionClose(PwmChannelSession *controller) {
|
||||||
|
serviceClose(&controller->s);
|
||||||
|
}
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
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,
|
|
||||||
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,
|
|
||||||
} PowerDomainId;
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
// rgltr_services.cpp (no changes needed here—just compile it once)
|
|
||||||
#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) {
|
|
||||||
// Service returns µV (microvolts) in a local u32:
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
// rgltr_services.h
|
|
||||||
// ========
|
|
||||||
// Minimal header declarations for rgltr‐related functionality.
|
|
||||||
// Any file that wants to call rgltrOpenSession(), rgltrGetVoltage(), etc. should
|
|
||||||
// simply do `#include "infonx.h"` (NOT infonx.cpp).
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <switch.h> // for Service, Result, hosversionBefore(), smGetService(), serviceClose(), etc.
|
|
||||||
#include "rgltr.h" // for RgltrSession, PowerDomainId, etc.
|
|
||||||
|
|
||||||
// Global service handle for "rgltr". Defined in infonx.cpp.
|
|
||||||
extern Service g_rgltrSrv;
|
|
||||||
|
|
||||||
// Open/close the "rgltr" service. You must call rgltrInitialize() (once) before using
|
|
||||||
// rgltrOpenSession() & friends. Call rgltrExit() when your app is shutting down.
|
|
||||||
Result rgltrInitialize(void);
|
|
||||||
void rgltrExit(void);
|
|
||||||
|
|
||||||
// Open a regulator session for the given PowerDomainId (e.g. CPU, GPU, DRAM).
|
|
||||||
// On success, (*session_out).s will contain a valid Service handle.
|
|
||||||
Result rgltrOpenSession(RgltrSession* session_out, PowerDomainId module_id);
|
|
||||||
|
|
||||||
// Query the current voltage (in microvolts, µV) from a previously opened session.
|
|
||||||
// Writes the result into *out_volt.
|
|
||||||
Result rgltrGetVoltage(RgltrSession* session, u32* out_volt);
|
|
||||||
|
|
||||||
// Close a previously opened regulator session.
|
|
||||||
void rgltrCloseSession(RgltrSession* session);
|
|
||||||
@@ -56,7 +56,7 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
|
|
||||||
// All constants pre-calculated and cached
|
// All constants pre-calculated and cached
|
||||||
static constexpr const char* const labels[] = {
|
static constexpr const char* const labels[] = {
|
||||||
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC"
|
"App ID", "Profile", "CPU", "GPU", "MEM", "SoC", "Board", "Skin", "Now", "Avg", "BAT", "PMIC", "FAN"
|
||||||
};
|
};
|
||||||
|
|
||||||
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
|
static constexpr u32 dataPositions[6] = {63-3+3, 200-1, 344-1-3, 200-1, 342-1, 321-1};
|
||||||
@@ -159,6 +159,10 @@ void BaseMenuGui::preDraw(tsl::gfx::Renderer* renderer) {
|
|||||||
renderer->drawString(displayStrings[21], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat voltage
|
renderer->drawString(displayStrings[21], false, dataPositions[0], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat voltage
|
||||||
renderer->drawString(displayStrings[23], false, positions[2] - 2, y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat Age
|
renderer->drawString(displayStrings[23], false, positions[2] - 2, y, SMALL_TEXT_SIZE, tsl::infoTextColor); // Bat Age
|
||||||
|
|
||||||
|
renderer->drawString(labels[12], false, positions[6], y, SMALL_TEXT_SIZE, tsl::sectionTextColor); // fan label
|
||||||
|
|
||||||
|
renderer->drawString(displayStrings[24], false, dataPositions[1], y, SMALL_TEXT_SIZE, tsl::infoTextColor); // fan speed
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Optimized refresh - now does all the string formatting once per second
|
// Optimized refresh - now does all the string formatting once per second
|
||||||
@@ -262,6 +266,8 @@ void BaseMenuGui::refresh()
|
|||||||
|
|
||||||
sprintf(displayStrings[23], "%u%%", context->PartLoad[HocClkPartLoad_BAT] / 1000);
|
sprintf(displayStrings[23], "%u%%", context->PartLoad[HocClkPartLoad_BAT] / 1000);
|
||||||
|
|
||||||
|
sprintf(displayStrings[24], "%u%%", context->PartLoad[HocClkPartLoad_FAN]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tsl::elm::Element* BaseMenuGui::baseUI()
|
tsl::elm::Element* BaseMenuGui::baseUI()
|
||||||
|
|||||||
@@ -27,7 +27,6 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../rgltr_services.h"
|
|
||||||
#include "../../ipc.h"
|
#include "../../ipc.h"
|
||||||
#include "base_gui.h"
|
#include "base_gui.h"
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,8 @@
|
|||||||
#include <algorithm> // for std::clamp
|
#include <algorithm> // for std::clamp
|
||||||
#include <math.h>
|
#include <math.h>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
#include "batLib.h"
|
#include <battery.h>
|
||||||
|
#include <pwm.h>
|
||||||
|
|
||||||
#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))
|
||||||
@@ -42,7 +43,6 @@
|
|||||||
#define systemtickfrequency 19200000
|
#define systemtickfrequency 19200000
|
||||||
#define systemtickfrequencyF 19200000.0f
|
#define systemtickfrequencyF 19200000.0f
|
||||||
#define CPU_TICK_WAIT (1'000'000'000 / 60)
|
#define CPU_TICK_WAIT (1'000'000'000 / 60)
|
||||||
float fanTemp = 0;
|
|
||||||
Result nvCheck = 1;
|
Result nvCheck = 1;
|
||||||
|
|
||||||
Thread gpuLThread;
|
Thread gpuLThread;
|
||||||
@@ -50,9 +50,14 @@ Thread cpuCore0Thread;
|
|||||||
Thread cpuCore1Thread;
|
Thread cpuCore1Thread;
|
||||||
Thread cpuCore2Thread;
|
Thread cpuCore2Thread;
|
||||||
Thread cpuCore3Thread;
|
Thread cpuCore3Thread;
|
||||||
|
Thread miscThread;
|
||||||
|
double temp = 0;
|
||||||
|
|
||||||
FanController fanController;
|
PwmChannelSession g_ICon;
|
||||||
Result fanCheck = 1;
|
Result pwmCheck = 1;
|
||||||
|
Result pwmDutyCycleCheck = 1;
|
||||||
|
double Rotation_Duty = 0;
|
||||||
|
u8 fanLevel;
|
||||||
|
|
||||||
uint32_t GPU_Load_u = 0, fd = 0;
|
uint32_t GPU_Load_u = 0, fd = 0;
|
||||||
BatteryChargeInfo info;
|
BatteryChargeInfo info;
|
||||||
@@ -142,6 +147,21 @@ void gpuLoadThread(void*) {
|
|||||||
} while(true);
|
} while(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void miscThreadFunc(void*) {
|
||||||
|
for(;;) {
|
||||||
|
if (R_SUCCEEDED(pwmCheck)) {
|
||||||
|
if (R_SUCCEEDED(pwmChannelSessionGetDutyCycle(&g_ICon, &temp))) {
|
||||||
|
temp *= 10;
|
||||||
|
temp = trunc(temp);
|
||||||
|
temp /= 10;
|
||||||
|
Rotation_Duty = 100.0 - temp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fanLevel = (u8)Rotation_Duty;
|
||||||
|
svcSleepThread(300'000'000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void Board::Initialize()
|
void Board::Initialize()
|
||||||
{
|
{
|
||||||
@@ -181,10 +201,10 @@ void Board::Initialize()
|
|||||||
rc = rgltrInitialize();
|
rc = rgltrInitialize();
|
||||||
ASSERT_RESULT_OK(rc, "rgltrInitialize");
|
ASSERT_RESULT_OK(rc, "rgltrInitialize");
|
||||||
|
|
||||||
if (R_SUCCEEDED(fanInitialize())) {
|
// if (R_SUCCEEDED(fanInitialize())) {
|
||||||
if (hosversionAtLeast(7,0,0)) fanCheck = fanOpenController(&fanController, 0x3D000001);
|
// if (hosversionAtLeast(7,0,0)) fanCheck = fanOpenController(&fanController, 0x3D000001);
|
||||||
else fanCheck = fanOpenController(&fanController, 1);
|
// else fanCheck = fanOpenController(&fanController, 1);
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
|
||||||
threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2);
|
threadCreate(&gpuLThread, gpuLoadThread, NULL, NULL, 0x1000, 0x3F, -2);
|
||||||
@@ -194,12 +214,19 @@ void Board::Initialize()
|
|||||||
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1);
|
threadCreate(&cpuCore1Thread, CheckCore, &idletick1, NULL, 0x1000, 0x10, 1);
|
||||||
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2);
|
threadCreate(&cpuCore2Thread, CheckCore, &idletick2, NULL, 0x1000, 0x10, 2);
|
||||||
threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3);
|
threadCreate(&cpuCore3Thread, CheckCore, &idletick3, NULL, 0x1000, 0x10, 3);
|
||||||
|
threadCreate(&miscThread, miscThreadFunc, NULL, NULL, 0x1000, 0x3F, 3);
|
||||||
|
|
||||||
threadStart(&cpuCore0Thread);
|
threadStart(&cpuCore0Thread);
|
||||||
threadStart(&cpuCore1Thread);
|
threadStart(&cpuCore1Thread);
|
||||||
threadStart(&cpuCore2Thread);
|
threadStart(&cpuCore2Thread);
|
||||||
threadStart(&cpuCore3Thread);
|
threadStart(&cpuCore3Thread);
|
||||||
|
threadStart(&miscThread);
|
||||||
batteryInfoInitialize();
|
batteryInfoInitialize();
|
||||||
|
|
||||||
|
if (hosversionAtLeast(6,0,0) && R_SUCCEEDED(pwmInitialize())) {
|
||||||
|
pwmCheck = pwmOpenSession2(&g_ICon, 0x3D000001);
|
||||||
|
}
|
||||||
|
|
||||||
FetchHardwareInfos();
|
FetchHardwareInfos();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -230,8 +257,10 @@ void Board::Exit()
|
|||||||
threadClose(&cpuCore1Thread);
|
threadClose(&cpuCore1Thread);
|
||||||
threadClose(&cpuCore2Thread);
|
threadClose(&cpuCore2Thread);
|
||||||
threadClose(&cpuCore3Thread);
|
threadClose(&cpuCore3Thread);
|
||||||
|
threadClose(&miscThread);
|
||||||
|
|
||||||
fanExit();
|
pwmChannelSessionClose(&g_ICon);
|
||||||
|
pwmExit();
|
||||||
rgltrExit();
|
rgltrExit();
|
||||||
batteryInfoExit();
|
batteryInfoExit();
|
||||||
}
|
}
|
||||||
@@ -578,6 +607,8 @@ std::uint32_t Board::GetPartLoad(SysClkPartLoad loadSource)
|
|||||||
case HocClkPartLoad_BAT:
|
case HocClkPartLoad_BAT:
|
||||||
batteryInfoGetChargeInfo(&info);
|
batteryInfoGetChargeInfo(&info);
|
||||||
return info.RawBatteryCharge;
|
return info.RawBatteryCharge;
|
||||||
|
case HocClkPartLoad_FAN:
|
||||||
|
return GetFanRotationLevel();
|
||||||
default:
|
default:
|
||||||
ASSERT_ENUM_VALID(SysClkPartLoad, loadSource);
|
ASSERT_ENUM_VALID(SysClkPartLoad, loadSource);
|
||||||
}
|
}
|
||||||
@@ -726,6 +757,6 @@ std::uint32_t Board::GetVoltage(HocClkVoltage voltage)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u8 Board::GetFanRotationLevel() {
|
u8 Board::GetFanRotationLevel() {
|
||||||
fanControllerGetRotationSpeedLevel(&fanController, &fanTemp);
|
return fanLevel;
|
||||||
return (u8)fanTemp;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
#include "errors.h"
|
#include "errors.h"
|
||||||
#include "ipc_service.h"
|
#include "ipc_service.h"
|
||||||
#include "kip.h"
|
#include "kip.h"
|
||||||
#include "i2c_reg.h"
|
#include <i2c.h>
|
||||||
#include "notification.h"
|
#include "notification.h"
|
||||||
|
|
||||||
#define HOSPPC_HAS_BOOST (hosversionAtLeast(7,0,0))
|
#define HOSPPC_HAS_BOOST (hosversionAtLeast(7,0,0))
|
||||||
@@ -587,8 +587,6 @@ bool ClockManager::RefreshContext()
|
|||||||
FileUtils::WriteContextToCsv(this->context);
|
FileUtils::WriteContextToCsv(this->context);
|
||||||
}
|
}
|
||||||
|
|
||||||
this->context->fanLevel = Board::GetFanRotationLevel();
|
|
||||||
|
|
||||||
return hasChanged;
|
return hasChanged;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
#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);
|
|
||||||
Reference in New Issue
Block a user