added CPU speed api and minarch frontend option

This commit is contained in:
Shaun Inman 2023-01-30 23:08:04 -05:00
parent d9af2b88d0
commit a6847e7ab4
6 changed files with 90 additions and 26 deletions

View file

@ -1,5 +1,9 @@
#!/bin/sh #!/bin/sh
# disable MicroSD card powersaving (should help reduce load stutter, test)
echo on > /sys/devices/b0238000.mmc/mmc_host/mmc0/power/control
echo on > /sys/devices/b0230000.mmc/mmc_host/mmc1/power/control
export SDCARD_PATH="/mnt/sdcard" export SDCARD_PATH="/mnt/sdcard"
export BIOS_PATH="$SDCARD_PATH/Bios" export BIOS_PATH="$SDCARD_PATH/Bios"
export SAVES_PATH="$SDCARD_PATH/Saves" export SAVES_PATH="$SDCARD_PATH/Saves"
@ -14,7 +18,11 @@ export LD_LIBRARY_PATH=$SYSTEM_PATH/lib:$LD_LIBRARY_PATH
mkdir -p "$LOGS_PATH" mkdir -p "$LOGS_PATH"
mkdir -p "$USERDATA_PATH/.minui" mkdir -p "$USERDATA_PATH/.minui"
CPU_PATH="/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor" echo userspace > /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor
export CPU_SPEED_MENU=504000
export CPU_SPEED_GAME=1296000
export CPU_SPEED_PERF=1488000 # improves binary launch times
export CPU_PATH=/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed
cd $(dirname "$0") cd $(dirname "$0")
@ -25,11 +33,10 @@ export EXEC_PATH=/tmp/minui_exec
touch "$EXEC_PATH" && sync touch "$EXEC_PATH" && sync
while [ -f "$EXEC_PATH" ]; do while [ -f "$EXEC_PATH" ]; do
echo ondemand > "$CPU_PATH"
./minui.elf &> $LOGS_PATH/minui.txt ./minui.elf &> $LOGS_PATH/minui.txt
echo performance > "$CPU_PATH" # overclock to speedup binary launch time
echo $CPU_SPEED_PERF > "$CPU_PATH"
sync sync
NEXT="/tmp/next" NEXT="/tmp/next"

View file

@ -22,6 +22,8 @@ enum {
}; };
int main(int argc , char* argv[]) { int main(int argc , char* argv[]) {
POW_setCPUSpeed(CPU_SPEED_MENU);
SDL_Surface* screen = GFX_init(MODE_MAIN); SDL_Surface* screen = GFX_init(MODE_MAIN);
InitSettings(); InitSettings();

View file

@ -1099,26 +1099,33 @@ void POW_powerOff(void) {
} }
#define BACKLIGHT_PATH "/sys/class/backlight/backlight.2/bl_power" #define BACKLIGHT_PATH "/sys/class/backlight/backlight.2/bl_power"
#define GOVERNOR_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_governor"
static char governor[128]; #define CPU_SPEED_SET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_setspeed"
#define CPU_SPEED_GET_PATH "/sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq"
static int previous_speed = CPU_SPEED_NORMAL;
void POW_setCPUSpeed(int speed) {
putInt(CPU_SPEED_SET_PATH, speed);
sync();
}
static void POW_enterSleep(void) { static void POW_enterSleep(void) {
SetRawVolume(0); SetRawVolume(0);
putInt(BACKLIGHT_PATH, FB_BLANK_POWERDOWN); putInt(BACKLIGHT_PATH, FB_BLANK_POWERDOWN);
// save current governor (either ondemand or performance) // TODO: not sure this is necessary
getFile(GOVERNOR_PATH, governor, 128); // previous_speed = getInt(CPU_SPEED_GET_PATH);
trimTrailingNewlines(governor); // POW_setCPUSpeed(CPU_SPEED_MENU);
putFile(GOVERNOR_PATH, "powersave");
sync(); sync();
} }
static void POW_exitSleep(void) { static void POW_exitSleep(void) {
putInt(BACKLIGHT_PATH, FB_BLANK_UNBLANK); putInt(BACKLIGHT_PATH, FB_BLANK_UNBLANK);
SetVolume(GetVolume()); SetVolume(GetVolume());
// restore previous governor // TODO: not sure this is necessary
putFile(GOVERNOR_PATH, governor); // POW_setCPUSpeed(previous_speed);
sync(); sync();
} }
static void POW_waitForWake(void) { static void POW_waitForWake(void) {

View file

@ -192,6 +192,12 @@ int POW_isCharging(void);
int POW_getBattery(void); int POW_getBattery(void);
void POW_setRumble(int strength); // 0-100 void POW_setRumble(int strength); // 0-100
#define CPU_SPEED_MENU 504000 // 240000 was having latency issues
#define CPU_SPEED_POWERSAVE 1104000
#define CPU_SPEED_NORMAL 1296000
#define CPU_SPEED_PERFORMANCE 1488000
void POW_setCPUSpeed(int speed);
/////////////////////////////// ///////////////////////////////
#endif #endif

View file

@ -54,6 +54,7 @@ static int optimize_text = 1;
static int show_debug = 0; static int show_debug = 0;
static int max_ff_speed = 3; // 4x static int max_ff_speed = 3; // 4x
static int fast_forward = 0; static int fast_forward = 0;
static int overclock = 1; // normal
static struct Renderer { static struct Renderer {
int src_w; int src_w;
@ -384,6 +385,7 @@ enum {
FE_OPT_SCANLINES, FE_OPT_SCANLINES,
FE_OPT_TEXT, FE_OPT_TEXT,
FE_OPT_TEARING, FE_OPT_TEARING,
FE_OPT_OVERCLOCK,
FE_OPT_DEBUG, FE_OPT_DEBUG,
FE_OPT_MAXFF, FE_OPT_MAXFF,
FE_OPT_COUNT, FE_OPT_COUNT,
@ -485,10 +487,16 @@ static char* shortcut_labels[] = {
"MENU+R2", "MENU+R2",
NULL, NULL,
}; };
static char* overclock_labels[] = {
"Powersave",
"Normal",
"Performance",
NULL,
};
enum { enum {
CONFIG_NONE, CONFIG_NONE,
CONFIG_GLOBAL, CONFIG_CONSOLE,
CONFIG_GAME, CONFIG_GAME,
}; };
@ -532,6 +540,16 @@ static struct Config {
.values = tearing_labels, .values = tearing_labels,
.labels = tearing_labels, .labels = tearing_labels,
}, },
[FE_OPT_OVERCLOCK] = {
.key = "minarch_cpu_speed",
.name = "CPU Speed",
.desc = "Over- or underclock the CPU to prioritize\npure performance or power savings.",
.default_value = 1,
.value = 1,
.count = 3,
.values = overclock_labels,
.labels = overclock_labels,
},
[FE_OPT_DEBUG] = { [FE_OPT_DEBUG] = {
.key = "minarch_debug_hud", .key = "minarch_debug_hud",
.name = "Debug HUD", .name = "Debug HUD",
@ -579,11 +597,21 @@ static void Config_getValue(char* cfg, const char* key, char* out_value) {
if (!tmp) tmp = strchr(out_value, '\r'); if (!tmp) tmp = strchr(out_value, '\r');
if (tmp) *tmp = '\0'; if (tmp) *tmp = '\0';
} }
static void setOverclock(int i) {
overclock = i;
switch (i) {
case 0: POW_setCPUSpeed(CPU_SPEED_POWERSAVE); break;
case 1: POW_setCPUSpeed(CPU_SPEED_NORMAL); break;
case 2: POW_setCPUSpeed(CPU_SPEED_PERFORMANCE); break;
}
}
static void Config_syncFrontend(int i, int value) { static void Config_syncFrontend(int i, int value) {
switch (i) { switch (i) {
case FE_OPT_SCANLINES: show_scanlines = value; renderer.src_w = 0; break; case FE_OPT_SCANLINES: show_scanlines = value; renderer.src_w = 0; break;
case FE_OPT_TEXT: optimize_text = value; renderer.src_w = 0; break; case FE_OPT_TEXT: optimize_text = value; renderer.src_w = 0; break;
case FE_OPT_TEARING: GFX_setVsync(value); break; case FE_OPT_TEARING: GFX_setVsync(value); break;
case FE_OPT_OVERCLOCK: setOverclock(value); break;
case FE_OPT_DEBUG: show_debug = value; break; case FE_OPT_DEBUG: show_debug = value; break;
case FE_OPT_MAXFF: max_ff_speed = value; break; case FE_OPT_MAXFF: max_ff_speed = value; break;
} }
@ -609,7 +637,7 @@ static void Config_read(void) {
char* cfg = allocFile(path); char* cfg = allocFile(path);
if (!cfg) return; if (!cfg) return;
config.loaded = override ? CONFIG_GAME : CONFIG_GLOBAL; config.loaded = override ? CONFIG_GAME : CONFIG_CONSOLE;
char key[256]; char key[256];
char value[256]; char value[256];
@ -676,7 +704,7 @@ static void Config_write(int override) {
if (config.loaded==CONFIG_GAME) unlink(path); if (config.loaded==CONFIG_GAME) unlink(path);
Config_getPath(path, CONFIG_WRITE_ALL); Config_getPath(path, CONFIG_WRITE_ALL);
} }
config.loaded = override ? CONFIG_GAME : CONFIG_GLOBAL; config.loaded = override ? CONFIG_GAME : CONFIG_CONSOLE;
FILE *file = fopen(path, "wb"); FILE *file = fopen(path, "wb");
if (!file) return; if (!file) return;
@ -711,7 +739,7 @@ static void Config_restore(void) {
sprintf(path, "%s/%s.cfg", core.config_dir, game.name); sprintf(path, "%s/%s.cfg", core.config_dir, game.name);
unlink(path); unlink(path);
} }
else if (config.loaded==CONFIG_GLOBAL) { else if (config.loaded==CONFIG_CONSOLE) {
sprintf(path, "%s/minarch.cfg", core.config_dir); sprintf(path, "%s/minarch.cfg", core.config_dir);
unlink(path); unlink(path);
} }
@ -2427,9 +2455,12 @@ void Menu_quit(void) {
void Menu_beforeSleep(void) { void Menu_beforeSleep(void) {
State_autosave(); State_autosave();
putFile(AUTO_RESUME_PATH, game.path + strlen(SDCARD_PATH)); putFile(AUTO_RESUME_PATH, game.path + strlen(SDCARD_PATH));
POW_setCPUSpeed(CPU_SPEED_MENU);
} }
void Menu_afterSleep(void) { void Menu_afterSleep(void) {
unlink(AUTO_RESUME_PATH); unlink(AUTO_RESUME_PATH);
setOverclock(overclock);
// POW_setCPUSpeed(CPU_SPEED_NORMAL);
} }
typedef struct MenuList MenuList; typedef struct MenuList MenuList;
@ -2659,7 +2690,7 @@ static MenuList OptionShortcuts_menu = {
static char* getSaveDesc(void) { static char* getSaveDesc(void) {
switch (config.loaded) { switch (config.loaded) {
case CONFIG_NONE: return "Using defaults."; break; case CONFIG_NONE: return "Using defaults."; break;
case CONFIG_GLOBAL: return "Using global config."; break; case CONFIG_CONSOLE: return "Using console config."; break;
case CONFIG_GAME: return "Using game config."; break; case CONFIG_GAME: return "Using game config."; break;
} }
} }
@ -2697,17 +2728,18 @@ static int OptionSaveChanges_onConfirm(MenuList* list, int i) {
switch (i) { switch (i) {
case 0: { case 0: {
Config_write(CONFIG_WRITE_ALL); Config_write(CONFIG_WRITE_ALL);
message = "Saved for all games."; message = "Saved for console.";
break; break;
} }
case 1: { case 1: {
Config_write(CONFIG_WRITE_GAME); Config_write(CONFIG_WRITE_GAME);
message = "Saved for this game."; message = "Saved for game.";
break; break;
} }
default: { default: {
Config_restore(); Config_restore();
message = "Restored defaults."; if (config.loaded) message = "Restored console defaults.";
else message = "Restored defaults.";
break; break;
} }
} }
@ -2739,8 +2771,8 @@ static MenuList OptionSaveChanges_menu = {
.type = MENU_LIST, .type = MENU_LIST,
.on_confirm = OptionSaveChanges_onConfirm, .on_confirm = OptionSaveChanges_onConfirm,
.items = (MenuItem[]){ .items = (MenuItem[]){
{"Save for all games"}, {"Save for console"},
{"Save for this game"}, {"Save for game"},
{"Restore defaults"}, {"Restore defaults"},
{NULL}, {NULL},
} }
@ -3146,6 +3178,8 @@ static int Menu_options(MenuList* list) {
return 0; return 0;
} }
static void Menu_loop(void) { static void Menu_loop(void) {
POW_setCPUSpeed(CPU_SPEED_MENU); // set Hz directly
fast_forward = 0; fast_forward = 0;
POW_enableAutosleep(); POW_enableAutosleep();
PAD_reset(); PAD_reset();
@ -3504,6 +3538,8 @@ static void Menu_loop(void) {
GFX_flip(screen); GFX_flip(screen);
POW_disableAutosleep(); POW_disableAutosleep();
if (!quit) setOverclock(overclock); // restore overclock value
} }
// TODO: move to POW_*? // TODO: move to POW_*?
@ -3561,7 +3597,11 @@ static void limitFF(void) {
uint64_t ff_frame_time = 1000000 / (core.fps * (max_ff_speed + 1)); // TODO: define this only when max_ff_speed changes uint64_t ff_frame_time = 1000000 / (core.fps * (max_ff_speed + 1)); // TODO: define this only when max_ff_speed changes
if (elapsed<ff_frame_time) { if (elapsed<ff_frame_time) {
int delay = (ff_frame_time - elapsed) / 1000; int delay = (ff_frame_time - elapsed) / 1000;
if (delay>0) SDL_Delay(delay); if (delay>0) {
// TODO: huh, this isn't causing the Tekken 3 hangs...
// printf("limitFF delay: %i\n", delay); fflush(stdout);
SDL_Delay(delay);
}
} }
last_time += ff_frame_time; last_time += ff_frame_time;
return; return;
@ -3571,6 +3611,7 @@ static void limitFF(void) {
} }
int main(int argc , char* argv[]) { int main(int argc , char* argv[]) {
setOverclock(overclock); // default to normal
// force a stack overflow to ensure asan is linked and actually working // force a stack overflow to ensure asan is linked and actually working
// char tmp[2]; // char tmp[2];
// tmp[2] = 'a'; // tmp[2] = 'a';

View file

@ -1233,6 +1233,7 @@ int main (int argc, char *argv[]) {
if (autoResume()) return 0; // nothing to do if (autoResume()) return 0; // nothing to do
dump("MinUI"); dump("MinUI");
POW_setCPUSpeed(CPU_SPEED_MENU);
SDL_Surface* screen = GFX_init(MODE_MAIN); SDL_Surface* screen = GFX_init(MODE_MAIN);
InitSettings(); InitSettings();