@@ -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)
10931093void 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
0 commit comments