Skip to content

Commit 2941a67

Browse files
committed
rg_system: Refuse overclock if the PLL isn't set to 480Mhz
This usually happens if the device was configured to run at less than 240Mhz or has power management enabled. A device running with a 320Mhz PLL can still be overclocked, but it's just not something I want to care about right now.
1 parent 4ef4132 commit 2941a67

4 files changed

Lines changed: 75 additions & 82 deletions

File tree

components/retro-go/rg_audio.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ void rg_audio_set_sample_rate(int sampleRate)
236236
{
237237
audio.driver->set_sample_rate(sampleRate);
238238
audio.sampleRate = sampleRate;
239+
RG_LOGI("Samplerate set to %d", audio.sampleRate);
239240
RELEASE_DEVICE();
240241
}
241242
}

components/retro-go/rg_gui.c

Lines changed: 17 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1532,41 +1532,24 @@ static rg_gui_event_t custom_zoom_cb(rg_gui_option_t *option, rg_gui_event_t eve
15321532
return RG_DIALOG_VOID;
15331533
}
15341534

1535-
static rg_gui_event_t overclock_update_cb(rg_gui_option_t *option, rg_gui_event_t event)
1536-
{
1537-
switch ((int)option->arg)
1538-
{
1539-
case 0:
1540-
#if CONFIG_IDF_TARGET_ESP32
1541-
if (event == RG_DIALOG_PREV)
1542-
rg_system_set_overclock(rg_system_get_overclock() - 1);
1543-
else if (event == RG_DIALOG_NEXT)
1544-
rg_system_set_overclock(rg_system_get_overclock() + 1);
1545-
sprintf(option->value, "%dMhz", 240 + (rg_system_get_overclock() * 40));
1546-
#endif
1547-
break;
1548-
case 1:
1549-
// sprintf(option->value, "%dMhz", RG_SCREEN_SPEED / 1000 / 1000);
1550-
break;
1551-
case 2:
1552-
// sprintf(option->value, "%dMhz", RG_STORAGE_SDSPI_SPEED / 1000 / 1000);
1553-
break;
1554-
}
1555-
return RG_DIALOG_VOID;
1556-
}
1557-
15581535
static rg_gui_event_t overclock_cb(rg_gui_option_t *option, rg_gui_event_t event)
15591536
{
1560-
if (event == RG_DIALOG_ENTER)
1561-
{
1562-
const rg_gui_option_t options[] = {
1563-
{0, _("CPU"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_update_cb},
1564-
{1, _("LCD"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_update_cb},
1565-
{2, _("SD"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_update_cb},
1566-
RG_DIALOG_END,
1567-
};
1568-
rg_gui_dialog(option->label, options, 0);
1569-
}
1537+
// if (event == RG_DIALOG_ENTER)
1538+
// {
1539+
// const rg_gui_option_t options[] = {
1540+
// {0, _("CPU"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_update_cb},
1541+
// {1, _("LCD"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_update_cb},
1542+
// {2, _("SD"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_update_cb},
1543+
// RG_DIALOG_END,
1544+
// };
1545+
// rg_gui_dialog(option->label, options, 0);
1546+
// }
1547+
if (event == RG_DIALOG_PREV)
1548+
rg_system_set_overclock(rg_system_get_overclock() - 1);
1549+
else if (event == RG_DIALOG_NEXT)
1550+
rg_system_set_overclock(rg_system_get_overclock() + 1);
1551+
int level = rg_system_get_overclock();
1552+
sprintf(option->value, "%dMhz", level < 0 ? (128 + (level + 4) * 32) : (240 + level * 40));
15701553
return RG_DIALOG_VOID;
15711554
}
15721555

@@ -2028,7 +2011,7 @@ void rg_gui_options_menu(void)
20282011
{0, _("Speed"), "-", RG_DIALOG_FLAG_NORMAL, &speedup_update_cb},
20292012
// {0, _("Misc options"), NULL, RG_DIALOG_FLAG_NORMAL, &misc_options_cb},
20302013
#if !RG_BUILD_RELEASE
2031-
{0, _("Overclock"), NULL, RG_DIALOG_FLAG_NORMAL, &overclock_cb},
2014+
{0, _("Overclock"), "-", RG_DIALOG_FLAG_NORMAL, &overclock_cb},
20322015
#endif
20332016
{0, _("Emulator options"), NULL, RG_DIALOG_FLAG_NORMAL, &app_options_cb},
20342017
RG_DIALOG_END,

components/retro-go/rg_system.c

Lines changed: 56 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -407,10 +407,10 @@ rg_app_t *rg_system_init(int sampleRate, const rg_handlers_t *handlers, void *_u
407407
.speed = 1.f,
408408
.sampleRate = sampleRate,
409409
.tickRate = 60,
410+
.tickTimeout = 3000000,
410411
.frameTime = 1000000 / 60,
411412
.frameskip = 1, // This can be overriden on a per-app basis if needed, do not set 0 here!
412413
.overclock = 0,
413-
.tickTimeout = 3000000,
414414
.lowMemoryMode = false,
415415
.enWatchdog = true,
416416
.isColdBoot = true,
@@ -1093,6 +1093,11 @@ int rg_system_get_log_level(void)
10931093
void rg_system_set_overclock(int level)
10941094
{
10951095
#if CONFIG_IDF_TARGET_ESP32
1096+
if (level < -4 || level > 3)
1097+
{
1098+
RG_LOGW("Invalid level %d, min:-4 max:3", level);
1099+
return;
1100+
}
10961101
// #include "driver/uart.h"
10971102
// None of this is documented by espressif but there are comments to be found in the file `rtc_clk.c`
10981103
#define I2C_BBPLL 0x66
@@ -1108,65 +1113,69 @@ void rg_system_set_overclock(int level)
11081113
extern uint8_t rom_i2c_readReg(uint8_t block, uint8_t host_id, uint8_t reg_add);
11091114
extern int uart_set_baudrate(int uart_num, uint32_t baud_rate);
11101115

1111-
static uint8_t BASE_ENDIV5, BASE_BBADC_DSMP, BASE_BBADC_OC_LREF, BASE_BBADC_OC_DIV_7_0, BASE_BBADC_OC_DCUR;
1112-
static bool BASE_SAVED = false;
1113-
if (!BASE_SAVED)
1114-
{
1115-
BASE_ENDIV5 = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_ENDIV5);
1116-
BASE_BBADC_DSMP = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_BBADC_DSMP);
1117-
BASE_BBADC_OC_LREF = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_LREF);
1118-
BASE_BBADC_OC_DIV_7_0 = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DIV_7_0);
1119-
BASE_BBADC_OC_DCUR = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DCUR);
1120-
BASE_SAVED = true;
1121-
}
1122-
1123-
uint8_t ENDIV5 = BASE_ENDIV5;
1124-
uint8_t BBADC_DSMP = BASE_BBADC_DSMP;
1125-
uint8_t BBADC_OC_LREF = BASE_BBADC_OC_LREF;
1126-
uint8_t BBADC_OC_DIV_7_0 = BASE_BBADC_OC_DIV_7_0;
1127-
uint8_t BBADC_OC_DCUR = BASE_BBADC_OC_DCUR;
1128-
1129-
if (level < -4 || level > 3)
1116+
uint8_t PREV_ENDIV5 = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_ENDIV5);
1117+
uint8_t PREV_BBADC_DSMP = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_BBADC_DSMP);
1118+
uint8_t PREV_BBADC_OC_LREF = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_LREF);
1119+
uint8_t PREV_BBADC_OC_DIV_7_0 = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DIV_7_0);
1120+
uint8_t PREV_BBADC_OC_DCUR = rom_i2c_readReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DCUR);
1121+
// It's important that the PLL is set at 480Mhz because we make many assumptions based on this.
1122+
// Not so much the speed itself, but the many related registers as well as the core voltage and current.
1123+
if (PREV_ENDIV5 != BBPLL_ENDIV5_VAL_480M || PREV_BBADC_DSMP != BBPLL_BBADC_DSMP_VAL_480M)
11301124
{
1131-
RG_LOGW("Invalid level %d, min:-4 max:3", level);
1125+
RG_LOGE("Expected to find a 480Mhz PLL.");
11321126
return;
11331127
}
1134-
else if (level != 0)
1135-
{
1136-
uint8_t div_ref = 0;
1137-
uint8_t div7_0 = (level + 4) * 8;
1138-
uint8_t div10_8 = 0;
1139-
uint8_t lref = 0;
1140-
uint8_t dcur = 6;
1141-
uint8_t bw = 3;
1142-
ENDIV5 = BBPLL_ENDIV5_VAL_480M;
1143-
BBADC_DSMP = BBPLL_BBADC_DSMP_VAL_480M;
1144-
BBADC_OC_LREF = (lref << 7) | (div10_8 << 4) | (div_ref);
1145-
BBADC_OC_DIV_7_0 = div7_0;
1146-
BBADC_OC_DCUR = (bw << 6) | dcur;
1147-
}
1128+
1129+
uint8_t div_ref = 0;
1130+
uint8_t div7_0 = (level + 4) * 8;
1131+
uint8_t div10_8 = 0;
1132+
uint8_t lref = 0;
1133+
uint8_t dcur = 6;
1134+
uint8_t bw = 3;
1135+
uint8_t ENDIV5 = BBPLL_ENDIV5_VAL_480M;
1136+
uint8_t BBADC_DSMP = BBPLL_BBADC_DSMP_VAL_480M;
1137+
uint8_t BBADC_OC_LREF = (lref << 7) | (div10_8 << 4) | (div_ref);
1138+
uint8_t BBADC_OC_DIV_7_0 = div7_0;
1139+
uint8_t BBADC_OC_DCUR = (bw << 6) | dcur;
11481140

11491141
RG_LOGW(" ");
1150-
RG_LOGW("BASE: %d %d %d %d %d", BASE_ENDIV5, BASE_BBADC_DSMP, BASE_BBADC_OC_LREF, BASE_BBADC_OC_DIV_7_0, BASE_BBADC_OC_DCUR);
1142+
RG_LOGW("BASE: %d %d %d %d %d", PREV_ENDIV5, PREV_BBADC_DSMP, PREV_BBADC_OC_LREF, PREV_BBADC_OC_DIV_7_0, PREV_BBADC_OC_DCUR);
11511143
RG_LOGW("NEW : %d %d %d %d %d", ENDIV5, BBADC_DSMP, BBADC_OC_LREF, BBADC_OC_DIV_7_0, BBADC_OC_DCUR);
11521144
RG_LOGW(" ");
1145+
rg_task_delay(20);
11531146

1154-
RG_LOGW("Preparing peripherals for the speed change...");
1155-
rg_task_delay(10); // Wait for the log to be sent
1156-
1157-
float overclock_ratio = (240 + (level * 40)) / 240.f;
1158-
rg_audio_set_sample_rate(app.sampleRate / overclock_ratio);
1159-
uart_set_baudrate(0, 115200 / overclock_ratio);
1160-
1161-
RG_LOGW("Updating clock registers!");
1162-
rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_ENDIV5, ENDIV5);
1163-
rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_BBADC_DSMP, BBADC_DSMP);
1147+
// rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_ENDIV5, ENDIV5);
1148+
// rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_BBADC_DSMP, BBADC_DSMP);
11641149
// rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_LREF, BBADC_OC_LREF);
11651150
rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DIV_7_0, BBADC_OC_DIV_7_0);
11661151
// rom_i2c_writeReg(I2C_BBPLL, I2C_BBPLL_HOSTID, I2C_BBPLL_OC_DCUR, BBADC_OC_DCUR);
1167-
RG_LOGW("Overclock applied!");
1152+
1153+
// RTC clock isn't affected by the CPU or APB clocks, so it remains our only reliable time measurement
1154+
// uint64_t t = esp_rtc_get_time_us2() + 1000000; // The original is slow because of a mutex, my version ignores it
1155+
// uint32_t cc = xthal_get_ccount(); // Obtain it *after* calling esp_rtc_get_time_us because it is slow
1156+
// while (esp_rtc_get_time_us2() < t)
1157+
// continue;
1158+
// int real_mhz = (int)ceil((xthal_get_ccount() - cc) / 1000000.0);
1159+
int calc_mhz = level < 0 ? (128 + (level + 4) * 32) : (240 + level * 40);
1160+
1161+
// Most audio devices rely on either the APB or the CPU clocks, which we've just skewed. So we have to
1162+
// compensate. The external DAC uses the APLL which is an independant clock source, no need to correct.
1163+
if (strcmp(rg_audio_get_sink()->name, "Ext DAC") != 0)
1164+
rg_audio_set_sample_rate(app.sampleRate * (240.0 / calc_mhz));
1165+
uart_set_baudrate(0, 115200.0 * (240.0 / calc_mhz));
1166+
// esp_timer_impl_update_apb_freq(80.0 / 240.0 * calc_mhz);
1167+
// ets_update_cpu_frequency(real_mhz);
1168+
1169+
// This is a lazy hack to report a more accurate emulation speed. Obviously this isn't a real solution.
1170+
static int original_tickRate = 0;
1171+
if (!original_tickRate)
1172+
original_tickRate = app.tickRate;
1173+
app.tickRate = original_tickRate * (240.f / calc_mhz);
11681174

11691175
app.overclock = level;
1176+
app.frameskip = 1;
1177+
1178+
RG_LOGW("Overclock applied: %dMhz (measured: %dMhz)", calc_mhz, 0);
11701179
#else
11711180
RG_LOGE("Overclock not supported on this platform!");
11721181
#endif

components/retro-go/rg_system.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,10 +166,10 @@ typedef struct
166166
float speed;
167167
int sampleRate;
168168
int tickRate;
169+
int tickTimeout;
169170
int frameTime;
170171
int frameskip;
171172
int overclock;
172-
int tickTimeout;
173173
bool lowMemoryMode;
174174
bool enWatchdog;
175175
bool isColdBoot;

0 commit comments

Comments
 (0)